Artifactory security policies are essential for maintaining the integrity, availability, and confidentiality of your artifact repositories. This comprehensive guide covers Java-based management of users, groups, permissions, security scans, and compliance policies.
Understanding Artifactory Security Components
Key Security Areas:
- Access Control: Users, groups, and permissions
- Authentication: LDAP, SAML, OAuth integration
- Authorization: Permission targets and fine-grained access control
- Security Scanning: Xray integration for vulnerability detection
- Compliance: License validation and policy enforcement
- Auditing: Security event logging and monitoring
Java Dependencies Setup
<dependencies> <!-- Artifactory Java Client --> <dependency> <groupId>org.jfrog.artifactory.client</groupId> <artifactId>artifactory-java-client-services</artifactId> <version>2.13.0</version> </dependency> <!-- Spring Security for integration --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>6.1.5</version> </dependency> <!-- JSON processing --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.16.1</version> </dependency> <!-- HTTP client --> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.12.0</version> </dependency> <!-- Encryption utilities --> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpkix-jdk18on</artifactId> <version>1.76</version> </dependency> </dependencies>
Artifactory Security Configuration Models
package com.example.artifactory.security;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.*;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SecurityPolicy {
private String name;
private String description;
private PolicyType type;
private List<PolicyRule> rules;
private Map<String, Object> conditions;
private PolicyAction action;
private boolean enabled;
private Date createdAt;
private Date updatedAt;
public enum PolicyType {
VULNERABILITY, LICENSE, COMPLIANCE, ACCESS, BUILD
}
public enum PolicyAction {
BLOCK, WARN, ALLOW, QUARANTINE, NOTIFY
}
// Constructors
public SecurityPolicy() {
this.rules = new ArrayList<>();
this.conditions = new HashMap<>();
this.enabled = true;
this.createdAt = new Date();
}
public SecurityPolicy(String name, PolicyType type) {
this();
this.name = name;
this.type = type;
}
// Getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public PolicyType getType() { return type; }
public void setType(PolicyType type) { this.type = type; }
public List<PolicyRule> getRules() { return rules; }
public void setRules(List<PolicyRule> rules) { this.rules = rules; }
public Map<String, Object> getConditions() { return conditions; }
public void setConditions(Map<String, Object> conditions) { this.conditions = conditions; }
public PolicyAction getAction() { return action; }
public void setAction(PolicyAction action) { this.action = action; }
public boolean isEnabled() { return enabled; }
public void setEnabled(boolean enabled) { this.enabled = enabled; }
public Date getCreatedAt() { return createdAt; }
public void setCreatedAt(Date createdAt) { this.createdAt = createdAt; }
public Date getUpdatedAt() { return updatedAt; }
public void setUpdatedAt(Date updatedAt) { this.updatedAt = updatedAt; }
// Builder methods
public SecurityPolicy withRule(PolicyRule rule) {
this.rules.add(rule);
return this;
}
public SecurityPolicy withCondition(String key, Object value) {
this.conditions.put(key, value);
return this;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class PolicyRule {
private String name;
private RuleCriteria criteria;
private Map<String, Object> parameters;
private int priority;
public enum RuleCriteria {
SEVERITY_GTE, LICENSE_TYPE, PACKAGE_TYPE,
REPOSITORY, AGE_DAYS, DOWNLOAD_COUNT
}
// Constructors
public PolicyRule() {
this.parameters = new HashMap<>();
this.priority = 1;
}
public PolicyRule(String name, RuleCriteria criteria) {
this();
this.name = name;
this.criteria = criteria;
}
// Getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public RuleCriteria getCriteria() { return criteria; }
public void setCriteria(RuleCriteria criteria) { this.criteria = criteria; }
public Map<String, Object> getParameters() { return parameters; }
public void setParameters(Map<String, Object> parameters) { this.parameters = parameters; }
public int getPriority() { return priority; }
public void setPriority(int priority) { this.priority = priority; }
// Builder methods
public PolicyRule withParameter(String key, Object value) {
this.parameters.put(key, value);
return this;
}
}
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PermissionTarget {
private String name;
private String includesPattern;
private String excludesPattern;
private List<Repository> repositories;
private Map<String, Principal> principals;
// Constructors
public PermissionTarget() {
this.repositories = new ArrayList<>();
this.principals = new HashMap<>();
this.includesPattern = "**";
this.excludesPattern = "";
}
public PermissionTarget(String name) {
this();
this.name = name;
}
// Getters and setters
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getIncludesPattern() { return includesPattern; }
public void setIncludesPattern(String includesPattern) { this.includesPattern = includesPattern; }
public String getExcludesPattern() { return excludesPattern; }
public void setExcludesPattern(String excludesPattern) { this.excludesPattern = excludesPattern; }
public List<Repository> getRepositories() { return repositories; }
public void setRepositories(List<Repository> repositories) { this.repositories = repositories; }
public Map<String, Principal> getPrincipals() { return principals; }
public void setPrincipals(Map<String, Principal> principals) { this.principals = principals; }
// Builder methods
public PermissionTarget withRepository(Repository repo) {
this.repositories.add(repo);
return this;
}
public PermissionTarget withPrincipal(String principalName, Principal principal) {
this.principals.put(principalName, principal);
return this;
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class Repository {
private String key;
private RepositoryType type;
public enum RepositoryType {
LOCAL, REMOTE, VIRTUAL, DISTRIBUTION
}
// Constructors, getters, setters
public Repository() {}
public Repository(String key, RepositoryType type) {
this.key = key;
this.type = type;
}
public String getKey() { return key; }
public void setKey(String key) { this.key = key; }
public RepositoryType getType() { return type; }
public void setType(RepositoryType type) { this.type = type; }
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class Principal {
private List<String> permissions;
// Constructors
public Principal() {
this.permissions = new ArrayList<>();
}
public Principal(List<String> permissions) {
this.permissions = permissions;
}
// Getters and setters
public List<String> getPermissions() { return permissions; }
public void setPermissions(List<String> permissions) { this.permissions = permissions; }
// Helper methods
public boolean hasPermission(String permission) {
return permissions.contains(permission);
}
}
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public class SecurityScanResult {
private String artifactPath;
private String scanId;
private Date scanDate;
private ScanStatus status;
private List<Vulnerability> vulnerabilities;
private List<LicenseViolation> licenseViolations;
private PolicyEvaluationResult policyResult;
public enum ScanStatus {
PASSED, FAILED, WARNING, PENDING, ERROR
}
// Constructors
public SecurityScanResult() {
this.vulnerabilities = new ArrayList<>();
this.licenseViolations = new ArrayList<>();
this.scanDate = new Date();
}
// Getters and setters
public String getArtifactPath() { return artifactPath; }
public void setArtifactPath(String artifactPath) { this.artifactPath = artifactPath; }
public String getScanId() { return scanId; }
public void setScanId(String scanId) { this.scanId = scanId; }
public Date getScanDate() { return scanDate; }
public void setScanDate(Date scanDate) { this.scanDate = scanDate; }
public ScanStatus getStatus() { return status; }
public void setStatus(ScanStatus status) { this.status = status; }
public List<Vulnerability> getVulnerabilities() { return vulnerabilities; }
public void setVulnerabilities(List<Vulnerability> vulnerabilities) { this.vulnerabilities = vulnerabilities; }
public List<LicenseViolation> getLicenseViolations() { return licenseViolations; }
public void setLicenseViolations(List<LicenseViolation> licenseViolations) { this.licenseViolations = licenseViolations; }
public PolicyEvaluationResult getPolicyResult() { return policyResult; }
public void setPolicyResult(PolicyEvaluationResult policyResult) { this.policyResult = policyResult; }
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class Vulnerability {
private String id;
private String severity;
private String component;
private String version;
private String description;
private List<String> fixedVersions;
// Getters and setters
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getSeverity() { return severity; }
public void setSeverity(String severity) { this.severity = severity; }
public String getComponent() { return component; }
public void setComponent(String component) { this.component = component; }
public String getVersion() { return version; }
public void setVersion(String version) { this.version = version; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public List<String> getFixedVersions() { return fixedVersions; }
public void setFixedVersions(List<String> fixedVersions) { this.fixedVersions = fixedVersions; }
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class LicenseViolation {
private String license;
private String component;
private String violationType;
// Getters and setters
public String getLicense() { return license; }
public void setLicense(String license) { this.license = license; }
public String getComponent() { return component; }
public void setComponent(String component) { this.component = component; }
public String getViolationType() { return violationType; }
public void setViolationType(String violationType) { this.violationType = violationType; }
}
@JsonInclude(JsonInclude.Include.NON_NULL)
public static class PolicyEvaluationResult {
private boolean passed;
private List<String> failedPolicies;
private List<String> warnings;
// Constructors
public PolicyEvaluationResult() {
this.failedPolicies = new ArrayList<>();
this.warnings = new ArrayList<>();
}
// Getters and setters
public boolean isPassed() { return passed; }
public void setPassed(boolean passed) { this.passed = passed; }
public List<String> getFailedPolicies() { return failedPolicies; }
public void setFailedPolicies(List<String> failedPolicies) { this.failedPolicies = failedPolicies; }
public List<String> getWarnings() { return warnings; }
public void setWarnings(List<String> warnings) { this.warnings = warnings; }
}
}
Artifactory Security Manager
package com.example.artifactory.security;
import org.jfrog.artifactory.client.Artifactory;
import org.jfrog.artifactory.client.ArtifactoryClientBuilder;
import org.jfrog.artifactory.client.model.repository.settings.impl.MavenRepositorySettingsImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import java.util.*;
import java.io.IOException;
public class ArtifactorySecurityManager {
private final Artifactory artifactory;
private final OkHttpClient httpClient;
private final ObjectMapper objectMapper;
private final String baseUrl;
private final String apiKey;
public ArtifactorySecurityManager(String url, String apiKey) {
this.baseUrl = url;
this.apiKey = apiKey;
this.artifactory = ArtifactoryClientBuilder.create()
.setUrl(url)
.setApiKey(apiKey)
.build();
this.httpClient = new OkHttpClient();
this.objectMapper = new ObjectMapper();
}
/**
* Create security policy
*/
public boolean createSecurityPolicy(SecurityPolicy policy) throws IOException {
String url = baseUrl + "/api/security/policies";
String jsonBody = objectMapper.writeValueAsString(policy);
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create(jsonBody, MediaType.parse("application/json")))
.header("X-JFrog-Art-Api", apiKey)
.build();
try (Response response = httpClient.newCall(request).execute()) {
return response.isSuccessful();
}
}
/**
* Get all security policies
*/
public List<SecurityPolicy> getSecurityPolicies() throws IOException {
String url = baseUrl + "/api/security/policies";
Request request = new Request.Builder()
.url(url)
.get()
.header("X-JFrog-Art-Api", apiKey)
.build();
try (Response response = httpClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Failed to fetch policies: " + response.message());
}
String responseBody = response.body().string();
return objectMapper.readValue(responseBody,
objectMapper.getTypeFactory().constructCollectionType(List.class, SecurityPolicy.class));
}
}
/**
* Create permission target
*/
public boolean createPermissionTarget(PermissionTarget permissionTarget) throws IOException {
String url = baseUrl + "/api/v2/security/permissions/" + permissionTarget.getName();
String jsonBody = objectMapper.writeValueAsString(permissionTarget);
Request request = new Request.Builder()
.url(url)
.put(RequestBody.create(jsonBody, MediaType.parse("application/json")))
.header("X-JFrog-Art-Api", apiKey)
.build();
try (Response response = httpClient.newCall(request).execute()) {
return response.isSuccessful();
}
}
/**
* Scan artifact for security issues
*/
public SecurityScanResult scanArtifact(String artifactPath) throws IOException {
String url = baseUrl + "/api/xray/scan";
Map<String, String> scanRequest = new HashMap<>();
scanRequest.put("path", artifactPath);
String jsonBody = objectMapper.writeValueAsString(scanRequest);
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create(jsonBody, MediaType.parse("application/json")))
.header("X-JFrog-Art-Api", apiKey)
.build();
try (Response response = httpClient.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Scan failed: " + response.message());
}
String responseBody = response.body().string();
return objectMapper.readValue(responseBody, SecurityScanResult.class);
}
}
/**
* Evaluate artifact against security policies
*/
public PolicyEvaluationResult evaluateArtifact(String artifactPath,
List<SecurityPolicy> policies) throws IOException {
SecurityScanResult scanResult = scanArtifact(artifactPath);
PolicyEvaluationResult evaluation = new PolicyEvaluationResult();
for (SecurityPolicy policy : policies) {
if (!policy.isEnabled()) continue;
boolean policyPassed = evaluatePolicy(scanResult, policy);
if (!policyPassed) {
evaluation.getFailedPolicies().add(policy.getName());
}
}
evaluation.setPassed(evaluation.getFailedPolicies().isEmpty());
return evaluation;
}
private boolean evaluatePolicy(SecurityScanResult scanResult, SecurityPolicy policy) {
switch (policy.getType()) {
case VULNERABILITY:
return evaluateVulnerabilityPolicy(scanResult, policy);
case LICENSE:
return evaluateLicensePolicy(scanResult, policy);
case COMPLIANCE:
return evaluateCompliancePolicy(scanResult, policy);
default:
return true;
}
}
private boolean evaluateVulnerabilityPolicy(SecurityScanResult scanResult, SecurityPolicy policy) {
for (SecurityPolicy.PolicyRule rule : policy.getRules()) {
if (rule.getCriteria() == SecurityPolicy.PolicyRule.RuleCriteria.SEVERITY_GTE) {
String minSeverity = (String) rule.getParameters().get("severity");
if (hasVulnerabilityWithSeverity(scanResult, minSeverity)) {
return false;
}
}
}
return true;
}
private boolean evaluateLicensePolicy(SecurityScanResult scanResult, SecurityPolicy policy) {
for (SecurityPolicy.PolicyRule rule : policy.getRules()) {
if (rule.getCriteria() == SecurityPolicy.PolicyRule.RuleCriteria.LICENSE_TYPE) {
String blockedLicense = (String) rule.getParameters().get("license");
if (hasLicenseViolation(scanResult, blockedLicense)) {
return false;
}
}
}
return true;
}
private boolean evaluateCompliancePolicy(SecurityScanResult scanResult, SecurityPolicy policy) {
// Implement compliance policy evaluation
// Check for specific compliance requirements
return true;
}
private boolean hasVulnerabilityWithSeverity(SecurityScanResult scanResult, String minSeverity) {
List<String> severityLevels = Arrays.asList("Low", "Medium", "High", "Critical");
int minSeverityIndex = severityLevels.indexOf(minSeverity);
for (SecurityScanResult.Vulnerability vuln : scanResult.getVulnerabilities()) {
int vulnSeverityIndex = severityLevels.indexOf(vuln.getSeverity());
if (vulnSeverityIndex >= minSeverityIndex) {
return true;
}
}
return false;
}
private boolean hasLicenseViolation(SecurityScanResult scanResult, String license) {
return scanResult.getLicenseViolations().stream()
.anyMatch(violation -> violation.getLicense().equalsIgnoreCase(license));
}
/**
* Create default security policies for an organization
*/
public List<SecurityPolicy> createDefaultPolicies() {
List<SecurityPolicy> policies = new ArrayList<>();
// Critical Vulnerability Policy
SecurityPolicy criticalVulnPolicy = new SecurityPolicy(
"block-critical-vulnerabilities",
SecurityPolicy.PolicyType.VULNERABILITY
);
criticalVulnPolicy.setDescription("Block artifacts with critical vulnerabilities");
criticalVulnPolicy.setAction(SecurityPolicy.PolicyAction.BLOCK);
SecurityPolicy.PolicyRule criticalRule = new SecurityPolicy.PolicyRule(
"critical-vulnerability-rule",
SecurityPolicy.PolicyRule.RuleCriteria.SEVERITY_GTE
);
criticalRule.withParameter("severity", "Critical");
criticalVulnPolicy.withRule(criticalRule);
policies.add(criticalVulnPolicy);
// High Vulnerability Policy
SecurityPolicy highVulnPolicy = new SecurityPolicy(
"warn-high-vulnerabilities",
SecurityPolicy.PolicyType.VULNERABILITY
);
highVulnPolicy.setDescription("Warn on high vulnerabilities");
highVulnPolicy.setAction(SecurityPolicy.PolicyAction.WARN);
SecurityPolicy.PolicyRule highRule = new SecurityPolicy.PolicyRule(
"high-vulnerability-rule",
SecurityPolicy.PolicyRule.RuleCriteria.SEVERITY_GTE
);
highRule.withParameter("severity", "High");
highVulnPolicy.withRule(highRule);
policies.add(highVulnPolicy);
// License Compliance Policy
SecurityPolicy licensePolicy = new SecurityPolicy(
"block-prohibited-licenses",
SecurityPolicy.PolicyType.LICENSE
);
licensePolicy.setDescription("Block artifacts with prohibited licenses");
licensePolicy.setAction(SecurityPolicy.PolicyAction.BLOCK);
SecurityPolicy.PolicyRule licenseRule = new SecurityPolicy.PolicyRule(
"prohibited-license-rule",
SecurityPolicy.PolicyRule.RuleCriteria.LICENSE_TYPE
);
licenseRule.withParameter("license", "AGPL-3.0");
licensePolicy.withRule(licenseRule);
policies.add(licensePolicy);
return policies;
}
/**
* Create default permission targets
*/
public List<PermissionTarget> createDefaultPermissionTargets() {
List<PermissionTarget> permissions = new ArrayList<>();
// Developers permission target
PermissionTarget devPermissions = new PermissionTarget("developers-read-write");
devPermissions.setIncludesPattern("**");
devPermissions.setExcludesPattern("");
PermissionTarget.Repository libsRepo = new PermissionTarget.Repository(
"libs-release-local",
PermissionTarget.Repository.RepositoryType.LOCAL
);
devPermissions.withRepository(libsRepo);
PermissionTarget.Principal devPrincipal = new PermissionTarget.Principal(
Arrays.asList("read", "write", "annotate", "delete")
);
devPermissions.withPrincipal("developers", devPrincipal);
permissions.add(devPermissions);
// Read-only permission target
PermissionTarget readOnlyPermissions = new PermissionTarget("read-only-users");
readOnlyPermissions.setIncludesPattern("**");
PermissionTarget.Principal readPrincipal = new PermissionTarget.Principal(
Arrays.asList("read")
);
readOnlyPermissions.withPrincipal("read-users", readPrincipal);
permissions.add(readOnlyPermissions);
return permissions;
}
}
Spring Boot Security Service
package com.example.artifactory.security;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Value;
import java.util.*;
@Service
public class ArtifactorySecurityService {
private final ArtifactorySecurityManager securityManager;
@Value("${artifactory.security.auto-create-policies:true}")
private boolean autoCreatePolicies;
@Value("${artifactory.security.block-critical-vulnerabilities:true}")
private boolean blockCriticalVulnerabilities;
public ArtifactorySecurityService(
@Value("${artifactory.url}") String artifactoryUrl,
@Value("${artifactory.api-key}") String apiKey) {
this.securityManager = new ArtifactorySecurityManager(artifactoryUrl, apiKey);
}
/**
* Initialize security policies and permissions
*/
public SecurityInitResult initializeSecurity() {
SecurityInitResult result = new SecurityInitResult();
try {
// Create default policies
List<SecurityPolicy> policies = securityManager.createDefaultPolicies();
for (SecurityPolicy policy : policies) {
boolean created = securityManager.createSecurityPolicy(policy);
if (created) {
result.getCreatedPolicies().add(policy.getName());
} else {
result.getFailedPolicies().add(policy.getName());
}
}
// Create default permission targets
List<PermissionTarget> permissions = securityManager.createDefaultPermissionTargets();
for (PermissionTarget permission : permissions) {
boolean created = securityManager.createPermissionTarget(permission);
if (created) {
result.getCreatedPermissions().add(permission.getName());
} else {
result.getFailedPermissions().add(permission.getName());
}
}
result.setSuccess(result.getFailedPolicies().isEmpty() &&
result.getFailedPermissions().isEmpty());
} catch (Exception e) {
result.setSuccess(false);
result.setErrorMessage("Security initialization failed: " + e.getMessage());
}
return result;
}
/**
* Validate artifact against security policies
*/
public ArtifactValidationResult validateArtifact(String artifactPath) {
ArtifactValidationResult result = new ArtifactValidationResult();
result.setArtifactPath(artifactPath);
try {
// Get all active policies
List<SecurityPolicy> policies = securityManager.getSecurityPolicies();
List<SecurityPolicy> activePolicies = policies.stream()
.filter(SecurityPolicy::isEnabled)
.toList();
// Evaluate artifact against policies
SecurityScanResult scanResult = securityManager.scanArtifact(artifactPath);
SecurityScanResult.PolicyEvaluationResult policyResult =
securityManager.evaluateArtifact(artifactPath, activePolicies);
result.setScanResult(scanResult);
result.setPolicyEvaluation(policyResult);
result.setValid(policyResult.isPassed());
// Determine if artifact should be blocked
if (!policyResult.isPassed() && blockCriticalVulnerabilities) {
result.setBlocked(true);
result.setBlockReason("Artifact violates security policies");
}
} catch (Exception e) {
result.setValid(false);
result.setError("Validation failed: " + e.getMessage());
}
return result;
}
/**
* Batch validate multiple artifacts
*/
public BatchValidationResult validateArtifacts(List<String> artifactPaths) {
BatchValidationResult result = new BatchValidationResult();
for (String artifactPath : artifactPaths) {
ArtifactValidationResult validation = validateArtifact(artifactPath);
result.getResults().put(artifactPath, validation);
if (!validation.isValid()) {
result.getInvalidArtifacts().add(artifactPath);
}
if (validation.isBlocked()) {
result.getBlockedArtifacts().add(artifactPath);
}
}
result.setAllValid(result.getInvalidArtifacts().isEmpty());
return result;
}
/**
* Get security compliance report
*/
public ComplianceReport generateComplianceReport(String repository) {
ComplianceReport report = new ComplianceReport();
report.setGeneratedDate(new Date());
report.setRepository(repository);
try {
// This would typically query Artifactory for repository contents
// and validate each artifact against policies
List<SecurityPolicy> policies = securityManager.getSecurityPolicies();
report.setActivePolicies(policies.size());
// Simulate compliance check
report.setTotalArtifacts(150);
report.setCompliantArtifacts(142);
report.setNonCompliantArtifacts(8);
report.setComplianceRate(94.67);
} catch (Exception e) {
report.setError("Failed to generate compliance report: " + e.getMessage());
}
return report;
}
// Result classes
public static class SecurityInitResult {
private boolean success;
private String errorMessage;
private List<String> createdPolicies;
private List<String> failedPolicies;
private List<String> createdPermissions;
private List<String> failedPermissions;
public SecurityInitResult() {
this.createdPolicies = new ArrayList<>();
this.failedPolicies = new ArrayList<>();
this.createdPermissions = new ArrayList<>();
this.failedPermissions = new ArrayList<>();
}
// Getters and setters
public boolean isSuccess() { return success; }
public void setSuccess(boolean success) { this.success = success; }
public String getErrorMessage() { return errorMessage; }
public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; }
public List<String> getCreatedPolicies() { return createdPolicies; }
public void setCreatedPolicies(List<String> createdPolicies) { this.createdPolicies = createdPolicies; }
public List<String> getFailedPolicies() { return failedPolicies; }
public void setFailedPolicies(List<String> failedPolicies) { this.failedPolicies = failedPolicies; }
public List<String> getCreatedPermissions() { return createdPermissions; }
public void setCreatedPermissions(List<String> createdPermissions) { this.createdPermissions = createdPermissions; }
public List<String> getFailedPermissions() { return failedPermissions; }
public void setFailedPermissions(List<String> failedPermissions) { this.failedPermissions = failedPermissions; }
}
public static class ArtifactValidationResult {
private String artifactPath;
private boolean valid;
private boolean blocked;
private String blockReason;
private String error;
private SecurityScanResult scanResult;
private SecurityScanResult.PolicyEvaluationResult policyEvaluation;
// Getters and setters
public String getArtifactPath() { return artifactPath; }
public void setArtifactPath(String artifactPath) { this.artifactPath = artifactPath; }
public boolean isValid() { return valid; }
public void setValid(boolean valid) { this.valid = valid; }
public boolean isBlocked() { return blocked; }
public void setBlocked(boolean blocked) { this.blocked = blocked; }
public String getBlockReason() { return blockReason; }
public void setBlockReason(String blockReason) { this.blockReason = blockReason; }
public String getError() { return error; }
public void setError(String error) { this.error = error; }
public SecurityScanResult getScanResult() { return scanResult; }
public void setScanResult(SecurityScanResult scanResult) { this.scanResult = scanResult; }
public SecurityScanResult.PolicyEvaluationResult getPolicyEvaluation() { return policyEvaluation; }
public void setPolicyEvaluation(SecurityScanResult.PolicyEvaluationResult policyEvaluation) { this.policyEvaluation = policyEvaluation; }
}
public static class BatchValidationResult {
private boolean allValid;
private Map<String, ArtifactValidationResult> results;
private List<String> invalidArtifacts;
private List<String> blockedArtifacts;
public BatchValidationResult() {
this.results = new HashMap<>();
this.invalidArtifacts = new ArrayList<>();
this.blockedArtifacts = new ArrayList<>();
}
// Getters and setters
public boolean isAllValid() { return allValid; }
public void setAllValid(boolean allValid) { this.allValid = allValid; }
public Map<String, ArtifactValidationResult> getResults() { return results; }
public void setResults(Map<String, ArtifactValidationResult> results) { this.results = results; }
public List<String> getInvalidArtifacts() { return invalidArtifacts; }
public void setInvalidArtifacts(List<String> invalidArtifacts) { this.invalidArtifacts = invalidArtifacts; }
public List<String> getBlockedArtifacts() { return blockedArtifacts; }
public void setBlockedArtifacts(List<String> blockedArtifacts) { this.blockedArtifacts = blockedArtifacts; }
}
public static class ComplianceReport {
private Date generatedDate;
private String repository;
private int totalArtifacts;
private int compliantArtifacts;
private int nonCompliantArtifacts;
private double complianceRate;
private int activePolicies;
private String error;
// Getters and setters
public Date getGeneratedDate() { return generatedDate; }
public void setGeneratedDate(Date generatedDate) { this.generatedDate = generatedDate; }
public String getRepository() { return repository; }
public void setRepository(String repository) { this.repository = repository; }
public int getTotalArtifacts() { return totalArtifacts; }
public void setTotalArtifacts(int totalArtifacts) { this.totalArtifacts = totalArtifacts; }
public int getCompliantArtifacts() { return compliantArtifacts; }
public void setCompliantArtifacts(int compliantArtifacts) { this.compliantArtifacts = compliantArtifacts; }
public int getNonCompliantArtifacts() { return nonCompliantArtifacts; }
public void setNonCompliantArtifacts(int nonCompliantArtifacts) { this.nonCompliantArtifacts = nonCompliantArtifacts; }
public double getComplianceRate() { return complianceRate; }
public void setComplianceRate(double complianceRate) { this.complianceRate = complianceRate; }
public int getActivePolicies() { return activePolicies; }
public void setActivePolicies(int activePolicies) { this.activePolicies = activePolicies; }
public String getError() { return error; }
public void setError(String error) { this.error = error; }
}
}
Spring Boot REST Controller
package com.example.artifactory.security;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import java.util.*;
@RestController
@RequestMapping("/api/security/artifactory")
public class ArtifactorySecurityController {
private final ArtifactorySecurityService securityService;
public ArtifactorySecurityController(ArtifactorySecurityService securityService) {
this.securityService = securityService;
}
@PostMapping("/initialize")
public ResponseEntity<ArtifactorySecurityService.SecurityInitResult> initializeSecurity() {
ArtifactorySecurityService.SecurityInitResult result =
securityService.initializeSecurity();
return ResponseEntity.ok(result);
}
@PostMapping("/validate")
public ResponseEntity<ArtifactorySecurityService.ArtifactValidationResult> validateArtifact(
@RequestBody ValidateArtifactRequest request) {
ArtifactorySecurityService.ArtifactValidationResult result =
securityService.validateArtifact(request.getArtifactPath());
return ResponseEntity.ok(result);
}
@PostMapping("/validate/batch")
public ResponseEntity<ArtifactorySecurityService.BatchValidationResult> validateArtifacts(
@RequestBody BatchValidateRequest request) {
ArtifactorySecurityService.BatchValidationResult result =
securityService.validateArtifacts(request.getArtifactPaths());
return ResponseEntity.ok(result);
}
@GetMapping("/compliance/{repository}")
public ResponseEntity<ArtifactorySecurityService.ComplianceReport> getComplianceReport(
@PathVariable String repository) {
ArtifactorySecurityService.ComplianceReport report =
securityService.generateComplianceReport(repository);
return ResponseEntity.ok(report);
}
@GetMapping("/policies")
public ResponseEntity<List<SecurityPolicy>> getSecurityPolicies() {
try {
ArtifactorySecurityManager securityManager = getSecurityManager();
List<SecurityPolicy> policies = securityManager.getSecurityPolicies();
return ResponseEntity.ok(policies);
} catch (Exception e) {
return ResponseEntity.badRequest().body(null);
}
}
@PostMapping("/policies")
public ResponseEntity<Map<String, Object>> createSecurityPolicy(
@RequestBody SecurityPolicy policy) {
try {
ArtifactorySecurityManager securityManager = getSecurityManager();
boolean created = securityManager.createSecurityPolicy(policy);
if (created) {
return ResponseEntity.ok(Map.of(
"success", true,
"message", "Policy created successfully"
));
} else {
return ResponseEntity.badRequest().body(Map.of(
"success", false,
"error", "Failed to create policy"
));
}
} catch (Exception e) {
return ResponseEntity.badRequest().body(Map.of(
"success", false,
"error", e.getMessage()
));
}
}
// Helper method to get security manager (in real app, inject properly)
private ArtifactorySecurityManager getSecurityManager() {
// This would be properly injected in a real application
return new ArtifactorySecurityManager(
"https://your-artifactory-instance.com",
"your-api-key"
);
}
// Request DTOs
public static class ValidateArtifactRequest {
private String artifactPath;
public String getArtifactPath() { return artifactPath; }
public void setArtifactPath(String artifactPath) { this.artifactPath = artifactPath; }
}
public static class BatchValidateRequest {
private List<String> artifactPaths;
public List<String> getArtifactPaths() { return artifactPaths; }
public void setArtifactPaths(List<String> artifactPaths) { this.artifactPaths = artifactPaths; }
}
}
CI/CD Pipeline Integration
package com.example.artifactory.security;
import java.util.List;
public class CICDSecurityGate {
private final ArtifactorySecurityService securityService;
public CICDSecurityGate(ArtifactorySecurityService securityService) {
this.securityService = securityService;
}
/**
* Check if artifact can be promoted based on security policies
*/
public PromotionResult checkPromotion(String artifactPath, String targetEnvironment) {
PromotionResult result = new PromotionResult();
result.setArtifactPath(artifactPath);
result.setTargetEnvironment(targetEnvironment);
ArtifactorySecurityService.ArtifactValidationResult validation =
securityService.validateArtifact(artifactPath);
result.setValidationResult(validation);
result.setCanPromote(validation.isValid() && !validation.isBlocked());
if (!result.isCanPromote()) {
result.setRejectionReason("Artifact failed security validation");
}
return result;
}
/**
* Security gate for deployment
*/
public DeploymentApproval checkDeploymentApproval(List<String> artifactPaths) {
DeploymentApproval approval = new DeploymentApproval();
ArtifactorySecurityService.BatchValidationResult batchResult =
securityService.validateArtifacts(artifactPaths);
approval.setValidationResult(batchResult);
approval.setApproved(batchResult.isAllValid() &&
batchResult.getBlockedArtifacts().isEmpty());
if (!approval.isApproved()) {
approval.setRejectionReasons(List.of(
"Some artifacts have security violations",
"Blocked artifacts: " + batchResult.getBlockedArtifacts()
));
}
return approval;
}
public static class PromotionResult {
private String artifactPath;
private String targetEnvironment;
private boolean canPromote;
private String rejectionReason;
private ArtifactorySecurityService.ArtifactValidationResult validationResult;
// Getters and setters
public String getArtifactPath() { return artifactPath; }
public void setArtifactPath(String artifactPath) { this.artifactPath = artifactPath; }
public String getTargetEnvironment() { return targetEnvironment; }
public void setTargetEnvironment(String targetEnvironment) { this.targetEnvironment = targetEnvironment; }
public boolean isCanPromote() { return canPromote; }
public void setCanPromote(boolean canPromote) { this.canPromote = canPromote; }
public String getRejectionReason() { return rejectionReason; }
public void setRejectionReason(String rejectionReason) { this.rejectionReason = rejectionReason; }
public ArtifactorySecurityService.ArtifactValidationResult getValidationResult() { return validationResult; }
public void setValidationResult(ArtifactorySecurityService.ArtifactValidationResult validationResult) { this.validationResult = validationResult; }
}
public static class DeploymentApproval {
private boolean approved;
private List<String> rejectionReasons;
private ArtifactorySecurityService.BatchValidationResult validationResult;
public DeploymentApproval() {
this.rejectionReasons = new ArrayList<>();
}
// Getters and setters
public boolean isApproved() { return approved; }
public void setApproved(boolean approved) { this.approved = approved; }
public List<String> getRejectionReasons() { return rejectionReasons; }
public void setRejectionReasons(List<String> rejectionReasons) { this.rejectionReasons = rejectionReasons; }
public ArtifactorySecurityService.BatchValidationResult getValidationResult() { return validationResult; }
public void setValidationResult(ArtifactorySecurityService.BatchValidationResult validationResult) { this.validationResult = validationResult; }
}
}
Best Practices for Production
- Principle of Least Privilege: Grant minimum required permissions
- Regular Policy Reviews: Review and update security policies quarterly
- Automated Scanning: Integrate security scans in CI/CD pipelines
- Compliance Monitoring: Continuously monitor for policy violations
- Audit Logging: Maintain comprehensive audit trails
- Secret Rotation: Regularly rotate API keys and credentials
- Backup Policies: Regularly backup security configurations
- Disaster Recovery: Plan for security configuration recovery
Conclusion
Implementing Artifactory security policies in Java provides a robust framework for securing your artifact repositories. The Java-based approach offers:
- Centralized Policy Management: Programmatically manage security policies
- Automated Compliance: Integrate security checks into development workflows
- Flexible Validation: Customize security rules for your organization
- CI/CD Integration: Enforce security gates in deployment pipelines
- Comprehensive Reporting: Generate security and compliance reports
By leveraging this Java-based security framework, organizations can maintain strong security postures, ensure compliance with internal and external requirements, and protect their software supply chain from vulnerabilities and license violations.