Cmprehensive Supply Chain Security with In-Toto Attestations
In-Toto provides a framework to secure software supply chains by cryptographically attesting to each step. This article covers comprehensive In-Toto attestation generation, verification, and management in Java with advanced features like policy enforcement, SLSA compliance, and automated provenance.
Core In-Toto Implementation
package com.titliel.intoto; import java.io.*; import java.nio.file.*; import java.security.*; import java.time.Instant; import java.util.*; import java.util.stream.Collectors; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; /** * Titliel In-Toto Attestation Framework * Comprehensive supply chain security with SLSA compliance */ public class TitlielInToto { private final InTotoConfig config; private final KeyManager keyManager; private final AttestationGenerator attestationGenerator; private final AttestationVerifier attestationVerifier; private final PolicyEngine policyEngine; private final ObjectMapper objectMapper; public TitlielInToto() { this.config = InTotoConfig.getInstance(); this.keyManager = new KeyManager(); this.attestationGenerator = new AttestationGenerator(); this.attestationVerifier = new AttestationVerifier(); this.policyEngine = new PolicyEngine(); this.objectMapper = new ObjectMapper() .configure(SerializationFeature.INDENT_OUTPUT, true) .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); initialize(); } private void initialize() { try { // Initialize key management keyManager.initialize(); // Load policies policyEngine.loadPolicies(); SecurityLogger.info("Titliel In-Toto framework initialized successfully"); } catch (Exception e) { SecurityLogger.error("Failed to initialize In-Toto framework", e); throw new InTotoException("Initialization failed", e); } } /** * Generate comprehensive attestation for a build step */ public AttestationResult generateAttestation(BuildContext context) { long startTime = System.currentTimeMillis(); AttestationResult result = new AttestationResult(context); try { // Validate build context validateBuildContext(context); // Generate step attestation StepAttestation stepAttestation = generateStepAttestation(context); // Generate material attestation MaterialAttestation materialAttestation = generateMaterialAttestation(context); // Generate product attestation ProductAttestation productAttestation = generateProductAttestation(context); // Generate provenance attestation ProvenanceAttestation provenance = generateProvenanceAttestation( context, stepAttestation, materialAttestation, productAttestation); // Generate link metadata LinkMetadata link = generateLinkMetadata(context, provenance); // Sign the attestation SignedAttestation signedAttestation = signAttestation(link); // Verify the attestation VerificationResult verification = verifyAttestation(signedAttestation); // Check policy compliance PolicyCompliance compliance = checkPolicyCompliance(signedAttestation, context); // Build result result.setStepAttestation(stepAttestation); result.setMaterialAttestation(materialAttestation); result.setProductAttestation(productAttestation); result.setProvenanceAttestation(provenance); result.setLinkMetadata(link); result.setSignedAttestation(signedAttestation); result.setVerificationResult(verification); result.setPolicyCompliance(compliance); result.setSuccess(true); // Store attestation storeAttestation(signedAttestation, context); SecurityLogger.info("Attestation generated successfully for build: {}", context.getBuildId()); } catch (Exception e) { result.setSuccess(false); result.setError(e.getMessage()); SecurityLogger.error("Failed to generate attestation", e); } finally { result.setGenerationTime(System.currentTimeMillis() - startTime); } return result; } /** * Generate step attestation */ private StepAttestation generateStepAttestation(BuildContext context) { StepAttestation attestation = new StepAttestation(); attestation.setStepName(context.getStepName()); attestation.setStepType(context.getStepType()); attestation.setCommand(context.getCommand()); attestation.setEnvironment(context.getEnvironment()); attestation.setWorkingDir(context.getWorkingDirectory()); attestation.setStartTime(Instant.now()); attestation.setEndTime(Instant.now()); // Will be updated // Capture environment details attestation.setEnvVars(System.getenv()); attestation.setSystemProperties(System.getProperties()); // Capture runtime information attestation.setJavaVersion(System.getProperty("java.version")); attestation.setOsName(System.getProperty("os.name")); attestation.setOsVersion(System.getProperty("os.version")); // Capture user information attestation.setUsername(System.getProperty("user.name")); attestation.setUserHome(System.getProperty("user.home")); return attestation; } /** * Generate material attestation */ private MaterialAttestation generateMaterialAttestation(BuildContext context) { MaterialAttestation attestation = new MaterialAttestation(); for (Path material : context.getMaterials()) { try { MaterialInfo materialInfo = createMaterialInfo(material); attestation.addMaterial(material, materialInfo); } catch (IOException e) { SecurityLogger.warn("Failed to process material: {}", material, e); attestation.addError(material, e.getMessage()); } } return attestation; } /** * Create material information with cryptographic hashes */ private MaterialInfo createMaterialInfo(Path material) throws IOException { MaterialInfo info = new MaterialInfo(); // Basic file information info.setPath(material.toString()); info.setSize(Files.size(material)); info.setLastModified(Files.getLastModifiedTime(material).toMillis()); // Calculate cryptographic hashes byte[] content = Files.readAllBytes(material); for (String algorithm : config.getHashAlgorithms()) { String hash = calculateHash(content, algorithm); info.addHash(algorithm, hash); } // Additional metadata if (Files.isSymbolicLink(material)) { info.setSymlinkTarget(Files.readSymbolicLink(material).toString()); } info.setPermissions(getFilePermissions(material)); info.setOwner(getFileOwner(material)); return info; } /** * Generate product attestation */ private ProductAttestation generateProductAttestation(BuildContext context) { ProductAttestation attestation = new ProductAttestation(); for (Path product : context.getProducts()) { try { ProductInfo productInfo = createProductInfo(product); attestation.addProduct(product, productInfo); } catch (IOException e) { SecurityLogger.warn("Failed to process product: {}", product, e); attestation.addError(product, e.getMessage()); } } return attestation; } /** * Create product information */ private ProductInfo createProductInfo(Path product) throws IOException { ProductInfo info = new ProductInfo(); // Basic file information info.setPath(product.toString()); info.setSize(Files.size(product)); info.setLastModified(Files.getLastModifiedTime(product).toMillis()); // Calculate cryptographic hashes byte[] content = Files.readAllBytes(product); for (String algorithm : config.getHashAlgorithms()) { String hash = calculateHash(content, algorithm); info.addHash(algorithm, hash); } // Additional metadata info.setPermissions(getFilePermissions(product)); info.setOwner(getFileOwner(product)); // Generate artifact URI info.setArtifactUri(generateArtifactUri(product)); return info; } /** * Generate provenance attestation */ private ProvenanceAttestation generateProvenanceAttestation(BuildContext context, StepAttestation step, MaterialAttestation materials, ProductAttestation products) { ProvenanceAttestation provenance = new ProvenanceAttestation(); provenance.setBuildId(context.getBuildId()); provenance.setBuildType(context.getBuildType()); provenance.setBuilder(context.getBuilder()); provenance.setInvocationId(context.getInvocationId()); provenance.setStartedAt(step.getStartTime()); provenance.setFinishedAt(Instant.now()); // Build configuration provenance.setBuildConfig(context.getBuildConfig()); // Materials and products provenance.setMaterials(materials.getMaterials()); provenance.setProducts(products.getProducts()); // Build steps provenance.setSteps(context.getBuildSteps()); // Metadata provenance.setMetadata(createProvenanceMetadata(context)); // SLSA compliance provenance.setSlsaLevel(calculateSlsaLevel(context, materials, products)); return provenance; } /** * Generate link metadata (in-toto link format) */ private LinkMetadata generateLinkMetadata(BuildContext context, ProvenanceAttestation provenance) { LinkMetadata link = new LinkMetadata(); link.setName(context.getStepName()); link.setMaterials(provenance.getMaterials()); link.setProducts(provenance.getProducts()); link.setByProducts(collectByProducts(context)); link.setCommand(context.getCommand()); link.setEnvironment(context.getEnvironment()); link.setWorkingDir(context.getWorkingDirectory()); return link; } /** * Sign the attestation */ private SignedAttestation signAttestation(LinkMetadata link) { try { // Serialize link metadata String json = objectMapper.writeValueAsString(link); byte[] data = json.getBytes(); // Sign with private key Signature signature = keyManager.sign(data); // Create signed attestation SignedAttestation signed = new SignedAttestation(); signed.setLinkMetadata(link); signed.setSignature(signature); signed.setKeyId(keyManager.getKeyId()); signed.setSigningTime(Instant.now()); return signed; } catch (Exception e) { throw new InTotoException("Failed to sign attestation", e); } } /** * Verify attestation signature and integrity */ private VerificationResult verifyAttestation(SignedAttestation attestation) { VerificationResult result = new VerificationResult(); try { // Verify signature boolean signatureValid = keyManager.verify( attestation.getLinkMetadata(), attestation.getSignature() ); result.setSignatureValid(signatureValid); // Verify link integrity result.setLinkIntegrity(verifyLinkIntegrity(attestation.getLinkMetadata())); // Verify material-product relationships result.setMaterialProductConsistency( verifyMaterialProductConsistency(attestation.getLinkMetadata())); // Calculate overall verification score result.calculateScore(); } catch (Exception e) { result.setError(e.getMessage()); SecurityLogger.error("Attestation verification failed", e); } return result; } /** * Check policy compliance */ private PolicyCompliance checkPolicyCompliance(SignedAttestation attestation, BuildContext context) { return policyEngine.evaluateCompliance(attestation, context); } /** * Store attestation for later verification */ private void storeAttestation(SignedAttestation attestation, BuildContext context) { try { // Create attestation directory Path attestationDir = getAttestationDirectory(context); Files.createDirectories(attestationDir); // Generate filename String filename = String.format("%s-%s.json", context.getBuildId(), Instant.now().toString().replace(":", "-")); Path attestationFile = attestationDir.resolve(filename); // Write attestation objectMapper.writeValue(attestationFile.toFile(), attestation); // Generate accompanying metadata storeAttestationMetadata(attestation, context, attestationFile); SecurityLogger.info("Attestation stored at: {}", attestationFile); } catch (Exception e) { SecurityLogger.error("Failed to store attestation", e); } } /** * Verify a complete supply chain */ public SupplyChainVerification verifySupplyChain(List<SignedAttestation> attestations, SupplyChainPolicy policy) { SupplyChainVerification result = new SupplyChainVerification(); try { // Verify individual attestations for (SignedAttestation attestation : attestations) { VerificationResult verification = verifyAttestation(attestation); result.addVerificationResult(attestation, verification); } // Verify chain continuity result.setChainContinuity(verifyChainContinuity(attestations)); // Verify policy compliance across chain result.setPolicyCompliance(verifyChainPolicyCompliance(attestations, policy)); // Calculate overall chain integrity result.calculateChainIntegrity(); } catch (Exception e) { result.setError(e.getMessage()); SecurityLogger.error("Supply chain verification failed", e); } return result; } /** * Generate SLSA provenance statement */ public SLSAProvenance generateSlsaProvenance(BuildContext context) { SLSAProvenance provenance = new SLSAProvenance(); provenance.setBuilder(context.getBuilder()); provenance.setBuildType(context.getBuildType()); provenance.setInvocation(context.getBuildInvocation()); provenance.setBuildConfig(context.getBuildConfig()); provenance.setMetadata(context.getBuildMetadata()); provenance.setMaterials(context.getMaterials().stream() .map(this::createSlsaMaterial) .collect(Collectors.toList())); provenance.setProducts(context.getProducts().stream() .map(this::createSlsaProduct) .collect(Collectors.toList())); return provenance; } /** * Verify SLSA provenance */ public SLSAVerification verifySlsaProvenance(SLSAProvenance provenance, SLSAPolicy policy) { SLSAVerification result = new SLSAVerification(); try { // Verify builder identity result.setBuilderVerified(verifyBuilderIdentity(provenance.getBuilder())); // Verify build invocation result.setInvocationVerified(verifyBuildInvocation(provenance.getInvocation())); // Verify materials result.setMaterialsVerified(verifyMaterials(provenance.getMaterials())); // Verify products result.setProductsVerified(verifyProducts(provenance.getProducts())); // Check SLSA level result.setSlsaLevel(calculateSlsaCompliance(provenance, policy)); } catch (Exception e) { result.setError(e.getMessage()); } return result; } // Utility methods private void validateBuildContext(BuildContext context) { List<String> errors = new ArrayList<>(); if (context.getBuildId() == null || context.getBuildId().isEmpty()) { errors.add("Build ID is required"); } if (context.getStepName() == null || context.getStepName().isEmpty()) { errors.add("Step name is required"); } if (context.getMaterials().isEmpty()) { errors.add("At least one material is required"); } if (context.getProducts().isEmpty()) { errors.add("At least one product is required"); } if (!errors.isEmpty()) { throw new InTotoException("Invalid build context: " + String.join(", ", errors)); } } private String calculateHash(byte[] data, String algorithm) { try { MessageDigest digest = MessageDigest.getInstance(algorithm); byte[] hash = digest.digest(data); return bytesToHex(hash); } catch (NoSuchAlgorithmException e) { throw new InTotoException("Unsupported hash algorithm: " + algorithm, e); } } private String bytesToHex(byte[] bytes) { StringBuilder result = new StringBuilder(); for (byte b : bytes) { result.append(String.format("%02x", b)); } return result.toString(); } private String getFilePermissions(Path path) { try { return PosixFilePermissions.toString(Files.getPosixFilePermissions(path)); } catch (Exception e) { return "unknown"; } } private String getFileOwner(Path path) { try { return Files.getOwner(path).getName(); } catch (Exception e) { return "unknown"; } } private String generateArtifactUri(Path product) { // Generate artifact URI based on configuration String baseUri = config.getArtifactBaseUri(); String relativePath = product.toString().replace(config.getBuildDirectory(), ""); return baseUri + relativePath; } private Map<String, Object> createProvenanceMetadata(BuildContext context) { Map<String, Object> metadata = new HashMap<>(); metadata.put("generatedAt", Instant.now().toString()); metadata.put("generator", "Titliel-InToto-Java"); metadata.put("version", "1.0.0"); metadata.put("buildTool", context.getBuildTool()); metadata.put("buildSystem", context.getBuildSystem()); return metadata; } private SLSALevel calculateSlsaLevel(BuildContext context, MaterialAttestation materials, ProductAttestation products) { // Implement SLSA level calculation based on requirements // This is a simplified implementation boolean hasProvenance = true; boolean hasHermeticBuild = context.isHermetic(); boolean hasReproducibleBuild = context.isReproducible(); boolean hasIsolatedBuild = context.isIsolated(); if (hasIsolatedBuild && hasReproducibleBuild && hasHermeticBuild) { return SLSALevel.LEVEL_4; } else if (hasHermeticBuild && hasReproducibleBuild) { return SLSALevel.LEVEL_3; } else if (hasProvenance) { return SLSALevel.LEVEL_2; } else { return SLSALevel.LEVEL_1; } } private Map<String, Object> collectByProducts(BuildContext context) { Map<String, Object> byProducts = new HashMap<>(); // Capture stdout/stderr if available if (context.getStdout() != null) { byProducts.put("stdout", context.getStdout()); } if (context.getStderr() != null) { byProducts.put("stderr", context.getStderr()); } // Capture return code byProducts.put("return-value", context.getReturnCode()); return byProducts; } private Path getAttestationDirectory(BuildContext context) { return Paths.get(config.getAttestationStore(), context.getBuildId(), context.getStepName()); } private void storeAttestationMetadata(SignedAttestation attestation, BuildContext context, Path attestationFile) throws IOException { AttestationMetadata metadata = new AttestationMetadata(); metadata.setBuildId(context.getBuildId()); metadata.setStepName(context.getStepName()); metadata.setAttestationFile(attestationFile.toString()); metadata.setGeneratedAt(Instant.now()); metadata.setSignatureKeyId(attestation.getKeyId()); Path metadataFile = attestationFile.getParent() .resolve(attestationFile.getFileName() + ".metadata.json"); objectMapper.writeValue(metadataFile.toFile(), metadata); } private boolean verifyLinkIntegrity(LinkMetadata link) { // Verify that materials and products actually exist // and match their hashes return true; // Implementation depends on actual verification logic } private boolean verifyMaterialProductConsistency(LinkMetadata link) { // Verify that all materials were consumed // and all products were produced return true; // Implementation depends on actual verification logic } private boolean verifyChainContinuity(List<SignedAttestation> attestations) { // Verify that each step's products become the next step's materials if (attestations.size() < 2) return true; for (int i = 0; i < attestations.size() - 1; i++) { SignedAttestation current = attestations.get(i); SignedAttestation next = attestations.get(i + 1); // Check product-material continuity if (!verifyStepContinuity(current, next)) { return false; } } return true; } private boolean verifyStepContinuity(SignedAttestation current, SignedAttestation next) { // Verify that next step's materials include current step's products // This is a simplified check return true; } private PolicyCompliance verifyChainPolicyCompliance(List<SignedAttestation> attestations, SupplyChainPolicy policy) { PolicyCompliance compliance = new PolicyCompliance(); for (SignedAttestation attestation : attestations) { // Check each attestation against policy // This would involve checking step types, commands, environments, etc. } return compliance; } private SLSAProvenance.Material createSlsaMaterial(Path material) { SLSAProvenance.Material slsaMaterial = new SLSAProvenance.Material(); try { byte[] content = Files.readAllBytes(material); String hash = calculateHash(content, "sha256"); slsaMaterial.setUri(generateArtifactUri(material)); slsaMaterial.setDigest(Map.of("sha256", hash)); } catch (IOException e) { SecurityLogger.warn("Failed to create SLSA material for: {}", material, e); } return slsaMaterial; } private SLSAProvenance.Product createSlsaProduct(Path product) { SLSAProvenance.Product slsaProduct = new SLSAProvenance.Product(); try { byte[] content = Files.readAllBytes(product); String hash = calculateHash(content, "sha256"); slsaProduct.setUri(generateArtifactUri(product)); slsaProduct.setDigest(Map.of("sha256", hash)); } catch (IOException e) { SecurityLogger.warn("Failed to create SLSA product for: {}", product, e); } return slsaProduct; } private boolean verifyBuilderIdentity(SLSAProvenance.Builder builder) { // Verify builder identity against trusted builders return config.getTrustedBuilders().contains(builder.getId()); } private boolean verifyBuildInvocation(SLSAProvenance.Invocation invocation) { // Verify build invocation parameters return true; // Implementation depends on policy } private boolean verifyMaterials(List<SLSAProvenance.Material> materials) { // Verify all materials are from trusted sources return materials.stream().allMatch(this::isTrustedMaterial); } private boolean verifyProducts(List<SLSAProvenance.Product> products) { // Verify all products have valid signatures/hashes return products.stream().allMatch(this::hasValidDigest); } private SLSALevel calculateSlsaCompliance(SLSAProvenance provenance, SLSAPolicy policy) { // Calculate SLSA compliance level based on policy return SLSALevel.LEVEL_3; // Simplified } private boolean isTrustedMaterial(SLSAProvenance.Material material) { // Check if material URI is from trusted source return material.getUri().startsWith(config.getTrustedSourcePrefix()); } private boolean hasValidDigest(SLSAProvenance.Product product) { // Verify product digest is present and valid return product.getDigest() != null && !product.getDigest().isEmpty(); } } Data Models and Attestation Structures
package com.titliel.intoto; import java.nio.file.Path; import java.time.Instant; import java.util.*; /** * Build context for attestation generation */ public class BuildContext { private String buildId; private String stepName; private StepType stepType; private List<Path> materials; private List<Path> products; private String command; private Map<String, String> environment; private Path workingDirectory; private String buildType; private String builder; private String invocationId; private Map<String, Object> buildConfig; private List<BuildStep> buildSteps; private Map<String, Object> buildMetadata; private String stdout; private String stderr; private int returnCode; private boolean hermetic; private boolean reproducible; private boolean isolated; private String buildTool; private String buildSystem; // Getters and setters public String getBuildId() { return buildId; } public void setBuildId(String buildId) { this.buildId = buildId; } public String getStepName() { return stepName; } public void setStepName(String stepName) { this.stepName = stepName; } public StepType getStepType() { return stepType; } public void setStepType(StepType stepType) { this.stepType = stepType; } public List<Path> getMaterials() { return materials; } public void setMaterials(List<Path> materials) { this.materials = materials; } public List<Path> getProducts() { return products; } public void setProducts(List<Path> products) { this.products = products; } public String getCommand() { return command; } public void setCommand(String command) { this.command = command; } public Map<String, String> getEnvironment() { return environment; } public void setEnvironment(Map<String, String> environment) { this.environment = environment; } public Path getWorkingDirectory() { return workingDirectory; } public void setWorkingDirectory(Path workingDirectory) { this.workingDirectory = workingDirectory; } public String getBuildType() { return buildType; } public void setBuildType(String buildType) { this.buildType = buildType; } public String getBuilder() { return builder; } public void setBuilder(String builder) { this.builder = builder; } public String getInvocationId() { return invocationId; } public void setInvocationId(String invocationId) { this.invocationId = invocationId; } public Map<String, Object> getBuildConfig() { return buildConfig; } public void setBuildConfig(Map<String, Object> buildConfig) { this.buildConfig = buildConfig; } public List<BuildStep> getBuildSteps() { return buildSteps; } public void setBuildSteps(List<BuildStep> buildSteps) { this.buildSteps = buildSteps; } public Map<String, Object> getBuildMetadata() { return buildMetadata; } public void setBuildMetadata(Map<String, Object> buildMetadata) { this.buildMetadata = buildMetadata; } public String getStdout() { return stdout; } public void setStdout(String stdout) { this.stdout = stdout; } public String getStderr() { return stderr; } public void setStderr(String stderr) { this.stderr = stderr; } public int getReturnCode() { return returnCode; } public void setReturnCode(int returnCode) { this.returnCode = returnCode; } public boolean isHermetic() { return hermetic; } public void setHermetic(boolean hermetic) { this.hermetic = hermetic; } public boolean isReproducible() { return reproducible; } public void setReproducible(boolean reproducible) { this.reproducible = reproducible; } public boolean isIsolated() { return isolated; } public void setIsolated(boolean isolated) { this.isolated = isolated; } public String getBuildTool() { return buildTool; } public void setBuildTool(String buildTool) { this.buildTool = buildTool; } public String getBuildSystem() { return buildSystem; } public void setBuildSystem(String buildSystem) { this.buildSystem = buildSystem; } } /** * Step types in supply chain */ public enum StepType { FETCH, BUILD, TEST, PACKAGE, SIGN, DEPLOY, VERIFY, CUSTOM } /** * Build step information */ public class BuildStep { private String name; private String type; private String command; private Map<String, String> environment; private Instant startTime; private Instant endTime; // Getters and setters public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getCommand() { return command; } public void setCommand(String command) { this.command = command; } public Map<String, String> getEnvironment() { return environment; } public void setEnvironment(Map<String, String> environment) { this.environment = environment; } public Instant getStartTime() { return startTime; } public void setStartTime(Instant startTime) { this.startTime = startTime; } public Instant getEndTime() { return endTime; } public void setEndTime(Instant endTime) { this.endTime = endTime; } } /** * Step attestation */ public class StepAttestation { private String stepName; private StepType stepType; private String command; private Map<String, String> environment; private Path workingDir; private Instant startTime; private Instant endTime; private Map<String, String> envVars; private Properties systemProperties; private String javaVersion; private String osName; private String osVersion; private String username; private String userHome; // Getters and setters public String getStepName() { return stepName; } public void setStepName(String stepName) { this.stepName = stepName; } public StepType getStepType() { return stepType; } public void setStepType(StepType stepType) { this.stepType = stepType; } public String getCommand() { return command; } public void setCommand(String command) { this.command = command; } public Map<String, String> getEnvironment() { return environment; } public void setEnvironment(Map<String, String> environment) { this.environment = environment; } public Path getWorkingDir() { return workingDir; } public void setWorkingDir(Path workingDir) { this.workingDir = workingDir; } public Instant getStartTime() { return startTime; } public void setStartTime(Instant startTime) { this.startTime = startTime; } public Instant getEndTime() { return endTime; } public void setEndTime(Instant endTime) { this.endTime = endTime; } public Map<String, String> getEnvVars() { return envVars; } public void setEnvVars(Map<String, String> envVars) { this.envVars = envVars; } public Properties getSystemProperties() { return systemProperties; } public void setSystemProperties(Properties systemProperties) { this.systemProperties = systemProperties; } public String getJavaVersion() { return javaVersion; } public void setJavaVersion(String javaVersion) { this.javaVersion = javaVersion; } public String getOsName() { return osName; } public void setOsName(String osName) { this.osName = osName; } public String getOsVersion() { return osVersion; } public void setOsVersion(String osVersion) { this.osName = osVersion; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getUserHome() { return userHome; } public void setUserHome(String userHome) { this.userHome = userHome; } } /** * Material attestation */ public class MaterialAttestation { private final Map<Path, MaterialInfo> materials; private final Map<Path, String> errors; public MaterialAttestation() { this.materials = new HashMap<>(); this.errors = new HashMap<>(); } public void addMaterial(Path path, MaterialInfo info) { materials.put(path, info); } public void addError(Path path, String error) { errors.put(path, error); } // Getters public Map<Path, MaterialInfo> getMaterials() { return Collections.unmodifiableMap(materials); } public Map<Path, String> getErrors() { return Collections.unmodifiableMap(errors); } public boolean hasErrors() { return !errors.isEmpty(); } } /** * Material information */ public class MaterialInfo { private String path; private long size; private long lastModified; private Map<String, String> hashes; private String symlinkTarget; private String permissions; private String owner; public MaterialInfo() { this.hashes = new HashMap<>(); } // Getters and setters public String getPath() { return path; } public void setPath(String path) { this.path = path; } public long getSize() { return size; } public void setSize(long size) { this.size = size; } public long getLastModified() { return lastModified; } public void setLastModified(long lastModified) { this.lastModified = lastModified; } public Map<String, String> getHashes() { return Collections.unmodifiableMap(hashes); } public void addHash(String algorithm, String hash) { hashes.put(algorithm, hash); } public String getSymlinkTarget() { return symlinkTarget; } public void setSymlinkTarget(String symlinkTarget) { this.symlinkTarget = symlinkTarget; } public String getPermissions() { return permissions; } public void setPermissions(String permissions) { this.permissions = permissions; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } } /** * Product attestation */ public class ProductAttestation { private final Map<Path, ProductInfo> products; private final Map<Path, String> errors; public ProductAttestation() { this.products = new HashMap<>(); this.errors = new HashMap<>(); } public void addProduct(Path path, ProductInfo info) { products.put(path, info); } public void addError(Path path, String error) { errors.put(path, error); } // Getters public Map<Path, ProductInfo> getProducts() { return Collections.unmodifiableMap(products); } public Map<Path, String> getErrors() { return Collections.unmodifiableMap(errors); } public boolean hasErrors() { return !errors.isEmpty(); } } /** * Product information */ public class ProductInfo { private String path; private long size; private long lastModified; private Map<String, String> hashes; private String permissions; private String owner; private String artifactUri; public ProductInfo() { this.hashes = new HashMap<>(); } // Getters and setters public String getPath() { return path; } public void setPath(String path) { this.path = path; } public long getSize() { return size; } public void setSize(long size) { this.size = size; } public long getLastModified() { return lastModified; } public void setLastModified(long lastModified) { this.lastModified = lastModified; } public Map<String, String> getHashes() { return Collections.unmodifiableMap(hashes); } public void addHash(String algorithm, String hash) { hashes.put(algorithm, hash); } public String getPermissions() { return permissions; } public void setPermissions(String permissions) { this.permissions = permissions; } public String getOwner() { return owner; } public void setOwner(String owner) { this.owner = owner; } public String getArtifactUri() { return artifactUri; } public void setArtifactUri(String artifactUri) { this.artifactUri = artifactUri; } } /** * Provenance attestation */ public class ProvenanceAttestation { private String buildId; private String buildType; private String builder; private String invocationId; private Instant startedAt; private Instant finishedAt; private Map<String, Object> buildConfig; private Map<Path, MaterialInfo> materials; private Map<Path, ProductInfo> products; private List<BuildStep> steps; private Map<String, Object> metadata; private SLSALevel slsaLevel; // Getters and setters public String getBuildId() { return buildId; } public void setBuildId(String buildId) { this.buildId = buildId; } public String getBuildType() { return buildType; } public void setBuildType(String buildType) { this.buildType = buildType; } public String getBuilder() { return builder; } public void setBuilder(String builder) { this.builder = builder; } public String getInvocationId() { return invocationId; } public void setInvocationId(String invocationId) { this.invocationId = invocationId; } public Instant getStartedAt() { return startedAt; } public void setStartedAt(Instant startedAt) { this.startedAt = startedAt; } public Instant getFinishedAt() { return finishedAt; } public void setFinishedAt(Instant finishedAt) { this.finishedAt = finishedAt; } public Map<String, Object> getBuildConfig() { return buildConfig; } public void setBuildConfig(Map<String, Object> buildConfig) { this.buildConfig = buildConfig; } public Map<Path, MaterialInfo> getMaterials() { return materials; } public void setMaterials(Map<Path, MaterialInfo> materials) { this.materials = materials; } public Map<Path, ProductInfo> getProducts() { return products; } public void setProducts(Map<Path, ProductInfo> products) { this.products = products; } public List<BuildStep> getSteps() { return steps; } public void setSteps(List<BuildStep> steps) { this.steps = steps; } public Map<String, Object> getMetadata() { return metadata; } public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; } public SLSALevel getSlsaLevel() { return slsaLevel; } public void setSlsaLevel(SLSALevel slsaLevel) { this.slsaLevel = slsaLevel; } } /** * Link metadata (in-toto link format) */ public class LinkMetadata { private String name; private Map<Path, MaterialInfo> materials; private Map<Path, ProductInfo> products; private Map<String, Object> byProducts; private String command; private Map<String, String> environment; private Path workingDir; // Getters and setters public String getName() { return name; } public void setName(String name) { this.name = name; } public Map<Path, MaterialInfo> getMaterials() { return materials; } public void setMaterials(Map<Path, MaterialInfo> materials) { this.materials = materials; } public Map<Path, ProductInfo> getProducts() { return products; } public void setProducts(Map<Path, ProductInfo> products) { this.products = products; } public Map<String, Object> getByProducts() { return byProducts; } public void setByProducts(Map<String, Object> byProducts) { this.byProducts = byProducts; } public String getCommand() { return command; } public void setCommand(String command) { this.command = command; } public Map<String, String> getEnvironment() { return environment; } public void setEnvironment(Map<String, String> environment) { this.environment = environment; } public Path getWorkingDir() { return workingDir; } public void setWorkingDir(Path workingDir) { this.workingDir = workingDir; } } /** * Signed attestation */ public class SignedAttestation { private LinkMetadata linkMetadata; private Signature signature; private String keyId; private Instant signingTime; // Getters and setters public LinkMetadata getLinkMetadata() { return linkMetadata; } public void setLinkMetadata(LinkMetadata linkMetadata) { this.linkMetadata = linkMetadata; } public Signature getSignature() { return signature; } public void setSignature(Signature signature) { this.signature = signature; } public String getKeyId() { return keyId; } public void setKeyId(String keyId) { this.keyId = keyId; } public Instant getSigningTime() { return signingTime; } public void setSigningTime(Instant signingTime) { this.signingTime = signingTime; } } /** * Attestation result */ public class AttestationResult { private final BuildContext context; private StepAttestation stepAttestation; private MaterialAttestation materialAttestation; private ProductAttestation productAttestation; private ProvenanceAttestation provenanceAttestation; private LinkMetadata linkMetadata; private SignedAttestation signedAttestation; private VerificationResult verificationResult; private PolicyCompliance policyCompliance; private boolean success; private String error; private long generationTime; public AttestationResult(BuildContext context) { this.context = context; } // Getters and setters public BuildContext getContext() { return context; } public StepAttestation getStepAttestation() { return stepAttestation; } public void setStepAttestation(StepAttestation stepAttestation) { this.stepAttestation = stepAttestation; } public MaterialAttestation getMaterialAttestation() { return materialAttestation; } public void setMaterialAttestation(MaterialAttestation materialAttestation) { this.materialAttestation = materialAttestation; } public ProductAttestation getProductAttestation() { return productAttestation; } public void setProductAttestation(ProductAttestation productAttestation) { this.productAttestation = productAttestation; } public ProvenanceAttestation getProvenanceAttestation() { return provenanceAttestation; } public void setProvenanceAttestation(ProvenanceAttestation provenanceAttestation) { this.provenanceAttestation = provenanceAttestation; } public LinkMetadata getLinkMetadata() { return linkMetadata; } public void setLinkMetadata(LinkMetadata linkMetadata) { this.linkMetadata = linkMetadata; } public SignedAttestation getSignedAttestation() { return signedAttestation; } public void setSignedAttestation(SignedAttestation signedAttestation) { this.signedAttestation = signedAttestation; } public VerificationResult getVerificationResult() { return verificationResult; } public void setVerificationResult(VerificationResult verificationResult) { this.verificationResult = verificationResult; } public PolicyCompliance getPolicyCompliance() { return policyCompliance; } public void setPolicyCompliance(PolicyCompliance policyCompliance) { this.policyCompliance = policyCompliance; } public boolean isSuccess() { return success; } public void setSuccess(boolean success) { this.success = success; } public String getError() { return error; } public void setError(String error) { this.error = error; } public long getGenerationTime() { return generationTime; } public void setGenerationTime(long generationTime) { this.generationTime = generationTime; } } /** * SLSA provenance model */ public class SLSAProvenance { private Builder builder; private String buildType; private Invocation invocation; private Map<String, Object> buildConfig; private Map<String, Object> metadata; private List<Material> materials; private List<Product> products; // Inner classes public static class Builder { private String id; private Map<String, String> builderDependencies; private String version; // Getters and setters public String getId() { return id; } public void setId(String id) { this.id = id; } public Map<String, String> getBuilderDependencies() { return builderDependencies; } public void setBuilderDependencies(Map<String, String> builderDependencies) { this.builderDependencies = builderDependencies; } public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } } public static class Invocation { private Map<String, Object> configSource; private Map<String, Object> parameters; private Map<String, Object> environment; // Getters and setters public Map<String, Object> getConfigSource() { return configSource; } public void setConfigSource(Map<String, Object> configSource) { this.configSource = configSource; } public Map<String, Object> getParameters() { return parameters; } public void setParameters(Map<String, Object> parameters) { this.parameters = parameters; } public Map<String, Object> getEnvironment() { return environment; } public void setEnvironment(Map<String, Object> environment) { this.environment = environment; } } public static class Material { private String uri; private Map<String, String> digest; private Map<String, Object> annotations; // Getters and setters public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } public Map<String, String> getDigest() { return digest; } public void setDigest(Map<String, String> digest) { this.digest = digest; } public Map<String, Object> getAnnotations() { return annotations; } public void setAnnotations(Map<String, Object> annotations) { this.annotations = annotations; } } public static class Product { private String uri; private Map<String, String> digest; private String name; // Getters and setters public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } public Map<String, String> getDigest() { return digest; } public void setDigest(Map<String, String> digest) { this.digest = digest; } public String getName() { return name; } public void setName(String name) { this.name = name; } } // Getters and setters public Builder getBuilder() { return builder; } public void setBuilder(Builder builder) { this.builder = builder; } public String getBuildType() { return buildType; } public void setBuildType(String buildType) { this.buildType = buildType; } public Invocation getInvocation() { return invocation; } public void setInvocation(Invocation invocation) { this.invocation = invocation; } public Map<String, Object> getBuildConfig() { return buildConfig; } public void setBuildConfig(Map<String, Object> buildConfig) { this.buildConfig = buildConfig; } public Map<String, Object> getMetadata() { return metadata; } public void setMetadata(Map<String, Object> metadata) { this.metadata = metadata; } public List<Material> getMaterials() { return materials; } public void setMaterials(List<Material> materials) { this.materials = materials; } public List<Product> getProducts() { return products; } public void setProducts(List<Product> products) { this.products = products; } } /** * SLSA levels */ public enum SLSALevel { LEVEL_0, LEVEL_1, LEVEL_2, LEVEL_3, LEVEL_4 } Key Management and Signing
package com.titliel.intoto; import java.security.*; import java.security.spec.*; import java.util.*; /** * Key management for attestation signing and verification */ public class KeyManager { private PrivateKey privateKey; private PublicKey publicKey; private String keyId; private String keyAlgorithm; public void initialize() { try { // Load or generate keys loadKeys(); // Generate key ID keyId = generateKeyId(); SecurityLogger.info("Key manager initialized with key ID: {}", keyId); } catch (Exception e) { throw new InTotoException("Failed to initialize key manager", e); } } private void loadKeys() throws Exception { // Try to load existing keys if (!tryLoadExistingKeys()) { // Generate new keys generateKeys(); saveKeys(); } } private boolean tryLoadExistingKeys() { try { Path privateKeyPath = getPrivateKeyPath(); Path publicKeyPath = getPublicKeyPath(); if (Files.exists(privateKeyPath) && Files.exists(publicKeyPath)) { // Load existing keys loadKeysFromFiles(privateKeyPath, publicKeyPath); return true; } } catch (Exception e) { SecurityLogger.warn("Failed to load existing keys", e); } return false; } private void generateKeys() throws Exception { // Generate RSA key pair KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); keyGen.initialize(4096); KeyPair keyPair = keyGen.generateKeyPair(); privateKey = keyPair.getPrivate(); publicKey = keyPair.getPublic(); keyAlgorithm = "rsa"; SecurityLogger.info("Generated new RSA 4096-bit key pair"); } private void saveKeys() throws Exception { // Save private key Path privateKeyPath = getPrivateKeyPath(); Files.createDirectories(privateKeyPath.getParent()); byte[] privateKeyBytes = privateKey.getEncoded(); Files.write(privateKeyPath, privateKeyBytes); // Save public key Path publicKeyPath = getPublicKeyPath(); byte[] publicKeyBytes = publicKey.getEncoded(); Files.write(publicKeyPath, publicKeyBytes); // Set secure permissions on private key setSecurePermissions(privateKeyPath); SecurityLogger.info("Keys saved to: {}", privateKeyPath.getParent()); } private void loadKeysFromFiles(Path privateKeyPath, Path publicKeyPath) throws Exception { // Load private key byte[] privateKeyBytes = Files.readAllBytes(privateKeyPath); PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); privateKey = keyFactory.generatePrivate(privateKeySpec); // Load public key byte[] publicKeyBytes = Files.readAllBytes(publicKeyPath); X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes); publicKey = keyFactory.generatePublic(publicKeySpec); keyAlgorithm = "rsa"; SecurityLogger.info("Loaded existing keys from: {}", privateKeyPath.getParent()); } private String generateKeyId() { try { // Generate key ID from public key fingerprint MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] fingerprint = digest.digest(publicKey.getEncoded()); // Take first 16 bytes for key ID StringBuilder keyIdBuilder = new StringBuilder(); for (int i = 0; i < 16; i++) { keyIdBuilder.append(String.format("%02x", fingerprint[i])); } return keyIdBuilder.toString(); } catch (Exception e) { throw new InTotoException("Failed to generate key ID", e); } } /** * Sign data with private key */ public Signature sign(byte[] data) throws Exception { Signature signature = Signature.getInstance("SHA256withRSA"); signature.initSign(privateKey); signature.update(data); byte[] signatureBytes = signature.sign(); SignatureResult result = new SignatureResult(); result.setAlgorithm("SHA256withRSA"); result.setSignature(signatureBytes); result.setKeyId(keyId); result.setTimestamp(Instant.now()); return result; } /** * Verify signature */ public boolean verify(LinkMetadata link, Signature signature) throws Exception { // Serialize link metadata ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(link); byte[] data = json.getBytes(); return verify(data, signature); } /** * Verify signature for raw data */ public boolean verify(byte[] data, Signature signature) throws Exception { Signature verifier = Signature.getInstance(signature.getAlgorithm()); verifier.initVerify(publicKey); verifier.update(data); return verifier.verify(signature.getSignature()); } /** * Get public key in PEM format */ public String getPublicKeyPem() { try { String base64Key = Base64.getEncoder().encodeToString(publicKey.getEncoded()); return String.format("-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----", base64Key.replaceAll("(.{64})", "$1\n").trim()); } catch (Exception e) { throw new InTotoException("Failed to generate PEM format", e); } } /** * Get key ID */ public String getKeyId() { return keyId; } private Path getPrivateKeyPath() { return Paths.get(InTotoConfig.getInstance().getKeyDirectory(), "private.key"); } private Path getPublicKeyPath() { return Paths.get(InTotoConfig.getInstance().getKeyDirectory(), "public.key"); } private void setSecurePermissions(Path path) throws IOException { // Set restrictive permissions on private key if (System.getProperty("os.name").toLowerCase().contains("linux")) { Files.setPosixFilePermissions(path, Set.of( PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE )); } } } /** * Signature representation */ public class Signature { private String algorithm; private byte[] signature; private String keyId; private Instant timestamp; // Getters and setters public String getAlgorithm() { return algorithm; } public void setAlgorithm(String algorithm) { this.algorithm = algorithm; } public byte[] getSignature() { return signature; } public void setSignature(byte[] signature) { this.signature = signature; } public String getKeyId() { return keyId; } public void setKeyId(String keyId) { this.keyId = keyId; } public Instant getTimestamp() { return timestamp; } public void setTimestamp(Instant timestamp) { this.timestamp = timestamp; } } Verification and Policy Engine
package com.titliel.intoto; import java.util.*; /** * Attestation verification engine */ public class AttestationVerifier { private final KeyManager keyManager; private final PolicyEngine policyEngine; public AttestationVerifier() { this.keyManager = new KeyManager(); this.policyEngine = new PolicyEngine(); } /** * Verify signed attestation */ public VerificationResult verify(SignedAttestation attestation) { VerificationResult result = new VerificationResult(); try { // Verify signature boolean signatureValid = keyManager.verify( attestation.getLinkMetadata(), attestation.getSignature() ); result.setSignatureValid(signatureValid); // Verify link metadata integrity result.setMetadataValid(verifyMetadata(attestation.getLinkMetadata())); // Verify material-product relationships result.setRelationshipsValid( verifyMaterialProductRelationships(attestation.getLinkMetadata())); // Calculate overall score result.calculateScore(); } catch (Exception e) { result.setError(e.getMessage()); SecurityLogger.error("Attestation verification failed", e); } return result; } /** * Verify metadata integrity */ private boolean verifyMetadata(LinkMetadata link) { // Check required fields if (link.getName() == null || link.getName().isEmpty()) { return false; } if (link.getMaterials() == null || link.getMaterials().isEmpty()) { return false; } if (link.getProducts() == null || link.getProducts().isEmpty()) { return false; } // Verify material hashes for (MaterialInfo material : link.getMaterials().values()) { if (!verifyMaterialHashes(material)) { return false; } } // Verify product hashes for (ProductInfo product : link.getProducts().values()) { if (!verifyProductHashes(product)) { return false; } } return true; } /** * Verify material hashes */ private boolean verifyMaterialHashes(MaterialInfo material) { if (material.getHashes() == null || material.getHashes().isEmpty()) { return false; } // At least one strong hash algorithm should be present Set<String> strongAlgorithms = Set.of("sha256", "sha512"); return material.getHashes().keySet().stream() .anyMatch(strongAlgorithms::contains); } /** * Verify product hashes */ private boolean verifyProductHashes(ProductInfo product) { if (product.getHashes() == null || product.getHashes().isEmpty()) { return false; } // At least one strong hash algorithm should be present Set<String> strongAlgorithms = Set.of("sha256", "sha512"); return product.getHashes().keySet().stream() .anyMatch(strongAlgorithms::contains); } /** * Verify material-product relationships */ private boolean verifyMaterialProductRelationships(LinkMetadata link) { // Basic validation: ensure materials and products are different Set<Path> materialPaths = link.getMaterials().keySet(); Set<Path> productPaths = link.getProducts().keySet(); // Check for obvious inconsistencies if (materialPaths.isEmpty() || productPaths.isEmpty()) { return false; } // Materials and products should generally be different files // (though self-modification is possible) return true; } /** * Verify supply chain continuity */ public ChainVerificationResult verifyChain(List<SignedAttestation> chain) { ChainVerificationResult result = new ChainVerificationResult(); if (chain.isEmpty()) { result.setError("Empty attestation chain"); return result; } // Verify each attestation individually List<VerificationResult> individualResults = new ArrayList<>(); for (SignedAttestation attestation : chain) { VerificationResult individual = verify(attestation); individualResults.add(individual); result.addIndividualResult(attestation, individual); } // Verify chain continuity boolean chainValid = verifyChainContinuity(chain); result.setChainContinuityValid(chainValid); // Verify policy compliance across chain PolicyCompliance chainCompliance = verifyChainPolicyCompliance(chain); result.setPolicyCompliance(chainCompliance); // Calculate overall chain integrity result.calculateChainIntegrity(); return result; } /** * Verify chain continuity */ private boolean verifyChainContinuity(List<SignedAttestation> chain) { for (int i = 0; i < chain.size() - 1; i++) { SignedAttestation current = chain.get(i); SignedAttestation next = chain.get(i + 1); if (!verifyStepContinuity(current, next)) { return false; } } return true; } /** * Verify continuity between two steps */ private boolean verifyStepContinuity(SignedAttestation current, SignedAttestation next) { // Get products from current step Map<Path, ProductInfo> currentProducts = current.getLinkMetadata().getProducts(); // Get materials from next step Map<Path, MaterialInfo> nextMaterials = next.getLinkMetadata().getMaterials(); // Verify that next step's materials include current step's products // This is a simplified check - real implementation would be more complex for (Path productPath : currentProducts.keySet()) { MaterialInfo nextMaterial = nextMaterials.get(productPath); if (nextMaterial == null) { // Product not found in next step's materials // Could be acceptable if product is not consumed continue; } // Verify hash consistency ProductInfo currentProduct = currentProducts.get(productPath); if (!verifyHashConsistency(currentProduct, nextMaterial)) { return false; } } return true; } /** * Verify hash consistency between product and material */ private boolean verifyHashConsistency(ProductInfo product, MaterialInfo material) { // Check if at least one hash algorithm matches for (Map.Entry<String, String> productHash : product.getHashes().entrySet()) { String materialHash = material.getHashes().get(productHash.getKey()); if (materialHash != null && materialHash.equals(productHash.getValue())) { return true; } } return false; } /** * Verify policy compliance across chain */ private PolicyCompliance verifyChainPolicyCompliance(List<SignedAttestation> chain) { PolicyCompliance compliance = new PolicyCompliance(); // Check each attestation against chain policies for (SignedAttestation attestation : chain) { PolicyCompliance individual = policyEngine.evaluateCompliance(attestation); compliance.merge(individual); } // Check chain-level policies compliance.merge(policyEngine.evaluateChainCompliance(chain)); return compliance; } } /** * Verification result */ public class VerificationResult { private boolean signatureValid; private boolean metadataValid; private boolean relationshipsValid; private double score; private String error; public void calculateScore() { int validCount = 0; int totalCount = 0; if (signatureValid) validCount++; totalCount++; if (metadataValid) validCount++; totalCount++; if (relationshipsValid) validCount++; totalCount++; this.score = (double) validCount / totalCount * 100.0; } // Getters and setters public boolean isSignatureValid() { return signatureValid; } public void setSignatureValid(boolean signatureValid) { this.signatureValid = signatureValid; } public boolean isMetadataValid() { return metadataValid; } public void setMetadataValid(boolean metadataValid) { this.metadataValid = metadataValid; } public boolean isRelationshipsValid() { return relationshipsValid; } public void setRelationshipsValid(boolean relationshipsValid) { this.relationshipsValid = relationshipsValid; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } public String getError() { return error; } public void setError(String error) { this.error = error; } public boolean isSuccess() { return signatureValid && metadataValid && relationshipsValid && score >= 80.0; } } /** * Chain verification result */ public class ChainVerificationResult { private final Map<SignedAttestation, VerificationResult> individualResults; private boolean chainContinuityValid; private PolicyCompliance policyCompliance; private double chainIntegrityScore; private String error; public ChainVerificationResult() { this.individualResults = new HashMap<>(); } public void addIndividualResult(SignedAttestation attestation, VerificationResult result) { individualResults.put(attestation, result); } public void calculateChainIntegrity() { if (individualResults.isEmpty()) { chainIntegrityScore = 0.0; return; } // Calculate average of individual scores double totalScore = individualResults.values().stream() .mapToDouble(VerificationResult::getScore) .sum(); double averageScore = totalScore / individualResults.size(); // Adjust for chain continuity if (chainContinuityValid) { averageScore *= 1.1; // Bonus for continuity } else { averageScore *= 0.5; // Penalty for broken chain } // Adjust for policy compliance if (policyCompliance != null && policyCompliance.isCompliant()) { averageScore *= 1.05; // Bonus for policy compliance } chainIntegrityScore = Math.min(averageScore, 100.0); } // Getters and setters public Map<SignedAttestation, VerificationResult> getIndividualResults() { return Collections.unmodifiableMap(individualResults); } public boolean isChainContinuityValid() { return chainContinuityValid; } public void setChainContinuityValid(boolean chainContinuityValid) { this.chainContinuityValid = chainContinuityValid; } public PolicyCompliance getPolicyCompliance() { return policyCompliance; } public void setPolicyCompliance(PolicyCompliance policyCompliance) { this.policyCompliance = policyCompliance; } public double getChainIntegrityScore() { return chainIntegrityScore; } public void setChainIntegrityScore(double chainIntegrityScore) { this.chainIntegrityScore = chainIntegrityScore; } public String getError() { return error; } public void setError(String error) { this.error = error; } public boolean isChainValid() { return chainIntegrityScore >= 80.0 && chainContinuityValid && (policyCompliance == null || policyCompliance.isCompliant()); } } /** * Policy engine for compliance checking */ public class PolicyEngine { private final List<PolicyRule> rules; private final Map<String, SupplyChainPolicy> policies; public PolicyEngine() { this.rules = new ArrayList<>(); this.policies = new HashMap<>(); loadDefaultRules(); } private void loadDefaultRules() { // Add default policy rules rules.add(new SignaturePolicyRule()); rules.add(new HashPolicyRule()); rules.add(new StepNamePolicyRule()); rules.add(new MaterialSourcePolicyRule()); rules.add(new ProductIntegrityPolicyRule()); } public void loadPolicies() { // Load policies from configuration InTotoConfig config = InTotoConfig.getInstance(); Path policyDir = Paths.get(config.getPolicyDirectory()); try { if (Files.exists(policyDir)) { Files.list(policyDir) .filter(path -> path.toString().endsWith(".json")) .forEach(this::loadPolicyFile); } } catch (IOException e) { SecurityLogger.warn("Failed to load policies from directory: {}", policyDir, e); } } private void loadPolicyFile(Path policyFile) { try { ObjectMapper mapper = new ObjectMapper(); SupplyChainPolicy policy = mapper.readValue(policyFile.toFile(), SupplyChainPolicy.class); policies.put(policy.getName(), policy); SecurityLogger.info("Loaded policy: {}", policy.getName()); } catch (IOException e) { SecurityLogger.warn("Failed to load policy file: {}", policyFile, e); } } /** * Evaluate attestation compliance */ public PolicyCompliance evaluateCompliance(SignedAttestation attestation) { PolicyCompliance compliance = new PolicyCompliance(); for (PolicyRule rule : rules) { RuleResult result = rule.evaluate(attestation); compliance.addRuleResult(rule.getName(), result); } // Check against specific policies for (SupplyChainPolicy policy : policies.values()) { if (policy.appliesTo(attestation)) { PolicyEvaluation evaluation = policy.evaluate(attestation); compliance.addPolicyEvaluation(policy.getName(), evaluation); } } compliance.calculateCompliance(); return compliance; } /** * Evaluate chain compliance */ public PolicyCompliance evaluateChainCompliance(List<SignedAttestation> chain) { PolicyCompliance compliance = new PolicyCompliance(); // Check chain-level policies for (SupplyChainPolicy policy : policies.values()) { if (policy.isChainPolicy()) { PolicyEvaluation evaluation = policy.evaluateChain(chain); compliance.addPolicyEvaluation(policy.getName(), evaluation); } } compliance.calculateCompliance(); return compliance; } } /** * Policy rule interface */ interface PolicyRule { String getName(); RuleResult evaluate(SignedAttestation attestation); } /** * Signature policy rule */ class SignaturePolicyRule implements PolicyRule { @Override public String getName() { return "signature-valid"; } @Override public RuleResult evaluate(SignedAttestation attestation) { RuleResult result = new RuleResult(getName()); try { // Check signature exists if (attestation.getSignature() == null) { result.setPassed(false); result.setMessage("No signature found"); return result; } // Check key ID exists if (attestation.getKeyId() == null || attestation.getKeyId().isEmpty()) { result.setPassed(false); result.setMessage("No key ID found"); return result; } // Check signature algorithm String algorithm = attestation.getSignature().getAlgorithm(); if (!isStrongAlgorithm(algorithm)) { result.setPassed(false); result.setMessage("Weak signature algorithm: " + algorithm); return result; } result.setPassed(true); result.setMessage("Signature valid"); } catch (Exception e) { result.setPassed(false); result.setMessage("Signature verification failed: " + e.getMessage()); } return result; } private boolean isStrongAlgorithm(String algorithm) { return algorithm.contains("SHA256") || algorithm.contains("SHA512"); } } /** * Hash policy rule */ class HashPolicyRule implements PolicyRule { @Override public String getName() { return "hash-integrity"; } @Override public RuleResult evaluate(SignedAttestation attestation) { RuleResult result = new RuleResult(getName()); LinkMetadata link = attestation.getLinkMetadata(); // Check materials have strong hashes for (MaterialInfo material : link.getMaterials().values()) { if (!hasStrongHash(material.getHashes())) { result.setPassed(false); result.setMessage("Material missing strong hash: " + material.getPath()); return result; } } // Check products have strong hashes for (ProductInfo product : link.getProducts().values()) { if (!hasStrongHash(product.getHashes())) { result.setPassed(false); result.setMessage("Product missing strong hash: " + product.getPath()); return result; } } result.setPassed(true); result.setMessage("All materials and products have strong hashes"); return result; } private boolean hasStrongHash(Map<String, String> hashes) { if (hashes == null || hashes.isEmpty()) { return false; } return hashes.containsKey("sha256") || hashes.containsKey("sha512"); } } Configuration and Usage Examples
```java
package com.titliel.intoto;
import java.nio.file.Paths;
import java.util.*;
/**
- Configuration management
*/
public class InTotoConfig { private static InTotoConfig instance;
private final Properties properties; private InTotoConfig() {
this.properties = loadProperties();
} public static synchronized InTotoConfig getInstance() {
if (instance == null) {
instance = new InTotoConfig();
}
return instance;
} private Properties loadProperties() {
Properties props = new Properties();// Load from system properties props.putAll(System.getProperties()); // Load from configuration file try { Path configFile = Paths.get("intoto.properties"); if (Files.exists(configFile)) { try (InputStream input = Files.newInputStream(configFile)) { props.load(input); } } } catch (IOException e) { // Use defaults } // Load from environment loadFromEnvironment(props); // Set defaults setDefaults(props); return props;} private void loadFrom
Advanced Java Container Security, Sandboxing & Trusted Runtime Environments
https://macronepal.com/blog/sandboxing-java-applications-implementing-landlock-lsm-for-enhanced-container-security/
Explains using Linux Landlock LSM to sandbox Java applications by restricting file system and resource access without root privileges, improving application-level isolation and reducing attack surface.
https://macronepal.com/blog/gvisor-sandbox-integration-in-java-complete-guide/
Explains integrating gVisor with Java to provide a user-space kernel sandbox that intercepts system calls and isolates applications from the host operating system for stronger security.
https://macronepal.com/blog/selinux-for-java-mandatory-access-control-for-jvm-applications/
Explains how SELinux enforces Mandatory Access Control (MAC) policies on Java applications, strictly limiting what files, processes, and network resources the JVM can access.
https://macronepal.com/java/a-comprehensive-guide-to-intel-sgx-sdk-integration-in-java/
Explains Intel SGX integration in Java, allowing sensitive code and data to run inside secure hardware enclaves that remain protected even if the OS is compromised.
https://macronepal.com/blog/building-a-microvm-runtime-with-aws-firecracker-in-java-a-comprehensive-guide/
Explains using AWS Firecracker microVMs with Java to run workloads in lightweight virtual machines that provide strong isolation with near-container performance efficiency.
https://macronepal.com/blog/enforcing-mandatory-access-control-implementing-apparmor-for-java-applications/
Explains AppArmor security profiles for Java applications, enforcing rules that restrict file access, execution rights, and system-level permissions.
https://macronepal.com/blog/rootless-containers-in-java-secure-container-operations-without-root/
Explains running Java applications in rootless containers using Linux user namespaces so containers operate securely without requiring root privileges.
https://macronepal.com/blog/unlocking-container-security-harnessing-user-namespaces-in-java/
Explains Linux user namespaces, which isolate user and group IDs inside containers to improve privilege separation and enhance container security for Java workloads.
https://macronepal.com/blog/secure-bootstrapping-in-java-comprehensive-trust-establishment-framework/
Explains secure bootstrapping in Java, focusing on how systems establish trust during startup using secure key management, identity verification, and trusted configuration loading.
https://macronepal.com/blog/securing-java-applications-with-chainguard-wolfi-a-comprehensive-guide-2/
Explains using Chainguard/Wolfi minimal container images to secure Java applications by reducing unnecessary packages, minimizing vulnerabilities, and providing a hardened runtime environment.