CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-amazonaws--aws-java-sdk-secretsmanager

Java client library for AWS Secrets Manager enabling secure storage, management, and retrieval of secrets.

Pending
Overview
Eval results
Files

policies-tags.mddocs/

Policies and Tagging

Resource-based access control through IAM policies and organizational management through resource tagging for governance, compliance, and cost allocation.

Resource Policy Management

Resource policies in AWS Secrets Manager control access to individual secrets using JSON policy documents. These policies work alongside IAM user/role policies to determine final permissions.

Getting Resource Policies

GetResourcePolicyRequest

class GetResourcePolicyRequest extends AmazonWebServiceRequest {
    String secretId;                          // Required: Secret identifier
}

GetResourcePolicyResult

class GetResourcePolicyResult {
    String arn;                               // Secret ARN
    String name;                              // Secret name
    String resourcePolicy;                    // JSON policy document
}

Usage Example

// Get current resource policy
GetResourcePolicyRequest getPolicyRequest = new GetResourcePolicyRequest()
    .withSecretId("prod/database/credentials");

try {
    GetResourcePolicyResult policyResult = client.getResourcePolicy(getPolicyRequest);
    
    System.out.println("Secret: " + policyResult.getName());
    System.out.println("Policy: " + policyResult.getResourcePolicy());
    
} catch (ResourceNotFoundException e) {
    System.out.println("No resource policy attached to this secret");
}

Setting Resource Policies

PutResourcePolicyRequest

class PutResourcePolicyRequest extends AmazonWebServiceRequest {
    String secretId;                          // Required: Secret identifier
    String resourcePolicy;                    // Required: JSON policy document
    Boolean blockPublicPolicy;                // Block policies that allow public access
}

PutResourcePolicyResult

class PutResourcePolicyResult {
    String arn;                               // Secret ARN
    String name;                              // Secret name
}

Usage Example

// Create a resource policy allowing cross-account access
String policyDocument = "{\n" +
    "  \"Version\": \"2012-10-17\",\n" +
    "  \"Statement\": [\n" +
    "    {\n" +
    "      \"Sid\": \"AllowCrossAccountRead\",\n" +
    "      \"Effect\": \"Allow\",\n" +
    "      \"Principal\": {\n" +
    "        \"AWS\": \"arn:aws:iam::123456789012:role/CrossAccountRole\"\n" +
    "      },\n" +
    "      \"Action\": [\n" +
    "        \"secretsmanager:GetSecretValue\",\n" +
    "        \"secretsmanager:DescribeSecret\"\n" +
    "      ],\n" +
    "      \"Resource\": \"*\",\n" +
    "      \"Condition\": {\n" +
    "        \"DateLessThan\": {\n" +
    "          \"aws:CurrentTime\": \"2024-12-31T23:59:59Z\"\n" +
    "        }\n" +
    "      }\n" +
    "    }\n" +
    "  ]\n" +
    "}";

PutResourcePolicyRequest putPolicyRequest = new PutResourcePolicyRequest()
    .withSecretId("shared/api/credentials")
    .withResourcePolicy(policyDocument)
    .withBlockPublicPolicy(true);

PutResourcePolicyResult putResult = client.putResourcePolicy(putPolicyRequest);
System.out.println("Resource policy applied to: " + putResult.getName());

Advanced Policy Examples

// Policy allowing access only from specific VPC
public String createVPCRestrictedPolicy(String allowedVpcId) {
    return "{\n" +
        "  \"Version\": \"2012-10-17\",\n" +
        "  \"Statement\": [\n" +
        "    {\n" +
        "      \"Sid\": \"AllowVPCAccess\",\n" +
        "      \"Effect\": \"Allow\",\n" +
        "      \"Principal\": {\n" +
        "        \"AWS\": \"*\"\n" +
        "      },\n" +
        "      \"Action\": \"secretsmanager:GetSecretValue\",\n" +
        "      \"Resource\": \"*\",\n" +
        "      \"Condition\": {\n" +
        "        \"StringEquals\": {\n" +
        "          \"aws:sourceVpc\": \"" + allowedVpcId + "\"\n" +
        "        }\n" +
        "      }\n" +
        "    }\n" +
        "  ]\n" +
        "}";
}

// Policy allowing access only during specific time window
public String createTimeRestrictedPolicy(String startTime, String endTime) {
    return "{\n" +
        "  \"Version\": \"2012-10-17\",\n" +
        "  \"Statement\": [\n" +
        "    {\n" +
        "      \"Sid\": \"AllowTimeWindowAccess\",\n" +
        "      \"Effect\": \"Allow\",\n" +
        "      \"Principal\": {\n" +
        "        \"AWS\": \"*\"\n" +
        "      },\n" +
        "      \"Action\": \"secretsmanager:GetSecretValue\",\n" +
        "      \"Resource\": \"*\",\n" +
        "      \"Condition\": {\n" +
        "        \"DateGreaterThan\": {\n" +
        "          \"aws:CurrentTime\": \"" + startTime + "\"\n" +
        "        },\n" +
        "        \"DateLessThan\": {\n" +
        "          \"aws:CurrentTime\": \"" + endTime + "\"\n" +
        "        }\n" +
        "      }\n" +
        "    }\n" +
        "  ]\n" +
        "}";
}

// Policy allowing read-only access to specific roles
public String createReadOnlyPolicy(List<String> allowedRoleArns) {
    StringBuilder principals = new StringBuilder();
    for (int i = 0; i < allowedRoleArns.size(); i++) {
        if (i > 0) principals.append(", ");
        principals.append("\"").append(allowedRoleArns.get(i)).append("\"");
    }
    
    return "{\n" +
        "  \"Version\": \"2012-10-17\",\n" +
        "  \"Statement\": [\n" +
        "    {\n" +
        "      \"Sid\": \"AllowReadOnlyAccess\",\n" +
        "      \"Effect\": \"Allow\",\n" +
        "      \"Principal\": {\n" +
        "        \"AWS\": [" + principals.toString() + "]\n" +
        "      },\n" +
        "      \"Action\": [\n" +
        "        \"secretsmanager:GetSecretValue\",\n" +
        "        \"secretsmanager:DescribeSecret\",\n" +
        "        \"secretsmanager:ListSecretVersionIds\"\n" +
        "      ],\n" +
        "      \"Resource\": \"*\"\n" +
        "    }\n" +
        "  ]\n" +
        "}";
}

Validating Resource Policies

ValidateResourcePolicyRequest

class ValidateResourcePolicyRequest extends AmazonWebServiceRequest {
    String secretId;                          // Secret identifier (optional for validation)
    String resourcePolicy;                    // Required: JSON policy document to validate
}

ValidateResourcePolicyResult

class ValidateResourcePolicyResult {
    Boolean policyValidationPassed;           // Whether validation passed
    List<ValidationErrorsEntry> validationErrors; // Validation errors if any
}

ValidationErrorsEntry

class ValidationErrorsEntry {
    String checkName;                         // Name of the validation check
    String errorMessage;                      // Detailed error message
}

Usage Example

// Validate a policy before applying it
String testPolicy = "{\n" +
    "  \"Version\": \"2012-10-17\",\n" +
    "  \"Statement\": [\n" +
    "    {\n" +
    "      \"Effect\": \"Allow\",\n" +
    "      \"Principal\": \"*\",\n" +  // This might trigger validation warnings
    "      \"Action\": \"secretsmanager:*\",\n" +
    "      \"Resource\": \"*\"\n" +
    "    }\n" +
    "  ]\n" +
    "}";

ValidateResourcePolicyRequest validateRequest = new ValidateResourcePolicyRequest()
    .withResourcePolicy(testPolicy)
    .withSecretId("test/secret");

ValidateResourcePolicyResult validateResult = client.validateResourcePolicy(validateRequest);

if (validateResult.getPolicyValidationPassed()) {
    System.out.println("Policy validation passed");
} else {
    System.out.println("Policy validation failed:");
    for (ValidationErrorsEntry error : validateResult.getValidationErrors()) {
        System.out.println("  " + error.getCheckName() + ": " + error.getErrorMessage());
    }
}

Deleting Resource Policies

DeleteResourcePolicyRequest

class DeleteResourcePolicyRequest extends AmazonWebServiceRequest {
    String secretId;                          // Required: Secret identifier
}

DeleteResourcePolicyResult

class DeleteResourcePolicyResult {
    String arn;                               // Secret ARN
    String name;                              // Secret name
}

Usage Example

// Remove resource policy from a secret
DeleteResourcePolicyRequest deleteRequest = new DeleteResourcePolicyRequest()
    .withSecretId("prod/database/credentials");

try {
    DeleteResourcePolicyResult deleteResult = client.deleteResourcePolicy(deleteRequest);
    System.out.println("Removed resource policy from: " + deleteResult.getName());
} catch (ResourceNotFoundException e) {
    System.out.println("No resource policy found to delete");
}

Tagging Management

Tags help organize secrets for cost allocation, access control, and operational management. Tags are key-value pairs that can be used in IAM policies and billing reports.

Adding Tags

TagResourceRequest

class TagResourceRequest extends AmazonWebServiceRequest {
    String secretId;                          // Required: Secret identifier
    List<Tag> tags;                           // Required: Tags to add
}

TagResourceResult

class TagResourceResult {
    // No properties - success indicated by no exception
}

Tag

class Tag {
    String key;                               // Required: Tag key (1-128 chars)
    String value;                             // Required: Tag value (0-256 chars)
}

Usage Example

// Add tags to a secret
List<Tag> tags = new ArrayList<>();
tags.add(new Tag().withKey("Environment").withValue("Production"));
tags.add(new Tag().withKey("Team").withValue("Backend"));
tags.add(new Tag().withKey("Application").withValue("UserService"));
tags.add(new Tag().withKey("CostCenter").withValue("Engineering"));
tags.add(new Tag().withKey("Owner").withValue("john.doe@company.com"));

TagResourceRequest tagRequest = new TagResourceRequest()
    .withSecretId("prod/user-service/db-credentials")
    .withTags(tags);

TagResourceResult tagResult = client.tagResource(tagRequest);
System.out.println("Tags added successfully");

// Add additional tags (existing tags remain)
List<Tag> additionalTags = new ArrayList<>();
additionalTags.add(new Tag().withKey("BackupSchedule").withValue("Daily"));
additionalTags.add(new Tag().withKey("Compliance").withValue("SOX"));

TagResourceRequest additionalTagRequest = new TagResourceRequest()
    .withSecretId("prod/user-service/db-credentials")
    .withTags(additionalTags);

client.tagResource(additionalTagRequest);

Removing Tags

UntagResourceRequest

class UntagResourceRequest extends AmazonWebServiceRequest {
    String secretId;                          // Required: Secret identifier
    List<String> tagKeys;                     // Required: Tag keys to remove
}

UntagResourceResult

class UntagResourceResult {
    // No properties - success indicated by no exception
}

Usage Example

// Remove specific tags
List<String> keysToRemove = Arrays.asList("BackupSchedule", "Compliance");

UntagResourceRequest untagRequest = new UntagResourceRequest()
    .withSecretId("prod/user-service/db-credentials")
    .withTagKeys(keysToRemove);

UntagResourceResult untagResult = client.untagResource(untagRequest);
System.out.println("Tags removed successfully");

Viewing Tags

Tags can be viewed through the DescribeSecret operation:

// View all tags on a secret
DescribeSecretRequest describeRequest = new DescribeSecretRequest()
    .withSecretId("prod/user-service/db-credentials");

DescribeSecretResult describeResult = client.describeSecret(describeRequest);

List<Tag> currentTags = describeResult.getTags();
if (currentTags != null && !currentTags.isEmpty()) {
    System.out.println("Current tags:");
    for (Tag tag : currentTags) {
        System.out.println("  " + tag.getKey() + " = " + tag.getValue());
    }
} else {
    System.out.println("No tags found");
}

Advanced Tag-Based Operations

Filtering Secrets by Tags

// List secrets filtered by specific tags
List<Filter> tagFilters = new ArrayList<>();

// Filter by tag key
tagFilters.add(new Filter()
    .withKey(FilterNameStringType.Tag_key)
    .withValues("Environment"));

// Filter by tag value
tagFilters.add(new Filter()
    .withKey(FilterNameStringType.Tag_value)
    .withValues("Production"));

ListSecretsRequest filteredRequest = new ListSecretsRequest()
    .withFilters(tagFilters);

ListSecretsResult filteredResult = client.listSecrets(filteredRequest);

System.out.println("Production secrets:");
for (SecretListEntry secret : filteredResult.getSecretList()) {
    System.out.println("  " + secret.getName());
    
    // Show relevant tags
    for (Tag tag : secret.getTags()) {
        if ("Environment".equals(tag.getKey()) || "Team".equals(tag.getKey())) {
            System.out.println("    " + tag.getKey() + ": " + tag.getValue());
        }
    }
}

Bulk Tagging Operations

// Apply consistent tags to multiple secrets
public void bulkTagSecrets(List<String> secretIds, List<Tag> commonTags) {
    for (String secretId : secretIds) {
        try {
            TagResourceRequest tagRequest = new TagResourceRequest()
                .withSecretId(secretId)
                .withTags(commonTags);
            
            client.tagResource(tagRequest);
            System.out.println("Tagged: " + secretId);
            
        } catch (Exception e) {
            System.err.println("Failed to tag " + secretId + ": " + e.getMessage());
        }
    }
}

// Example usage
List<String> productionSecrets = Arrays.asList(
    "prod/database/primary",
    "prod/database/replica",
    "prod/api/external-service",
    "prod/cache/redis"
);

List<Tag> productionTags = Arrays.asList(
    new Tag().withKey("Environment").withValue("Production"),
    new Tag().withKey("MonitoringLevel").withValue("Critical"),
    new Tag().withKey("BackupRequired").withValue("Yes")
);

bulkTagSecrets(productionSecrets, productionTags);

Tag-Based Cost Allocation

// Create cost allocation tags for billing
public void setupCostAllocationTags(String secretId, String project, 
                                   String department, String costCenter) {
    List<Tag> costTags = new ArrayList<>();
    costTags.add(new Tag().withKey("Project").withValue(project));
    costTags.add(new Tag().withKey("Department").withValue(department));
    costTags.add(new Tag().withKey("CostCenter").withValue(costCenter));
    costTags.add(new Tag().withKey("BillingMonth").withValue("2024-01"));
    
    TagResourceRequest costTagRequest = new TagResourceRequest()
        .withSecretId(secretId)
        .withTags(costTags);
    
    client.tagResource(costTagRequest);
    System.out.println("Cost allocation tags applied");
}

// Usage
setupCostAllocationTags("prod/app/database", "WebApp", "Engineering", "ENG001");

Tag-Based Access Control

// Create IAM policy condition based on tags
public String createTagBasedAccessPolicy(String tagKey, String tagValue) {
    return "{\n" +
        "  \"Version\": \"2012-10-17\",\n" +
        "  \"Statement\": [\n" +
        "    {\n" +
        "      \"Effect\": \"Allow\",\n" +
        "      \"Action\": [\n" +
        "        \"secretsmanager:GetSecretValue\",\n" +
        "        \"secretsmanager:DescribeSecret\"\n" +
        "      ],\n" +
        "      \"Resource\": \"*\",\n" +
        "      \"Condition\": {\n" +
        "        \"StringEquals\": {\n" +
        "          \"secretsmanager:ResourceTag/" + tagKey + "\": \"" + tagValue + "\"\n" +
        "        }\n" +
        "      }\n" +
        "    }\n" +
        "  ]\n" +
        "}";
}

// This policy allows access only to secrets tagged with Team=Backend
String backendTeamPolicy = createTagBasedAccessPolicy("Team", "Backend");

Compliance and Governance

Compliance Tagging Standards

public class ComplianceTagManager {
    
    // Standard compliance tags
    public static final String CLASSIFICATION_KEY = "DataClassification";
    public static final String RETENTION_KEY = "RetentionPeriod";
    public static final String COMPLIANCE_KEY = "ComplianceFramework";
    public static final String REVIEWED_KEY = "LastReviewed";
    
    public void applyComplianceTags(String secretId, String classification, 
                                   String retentionPeriod, List<String> frameworks) {
        List<Tag> complianceTags = new ArrayList<>();
        
        complianceTags.add(new Tag()
            .withKey(CLASSIFICATION_KEY)
            .withValue(classification)); // "Public", "Internal", "Confidential", "Restricted"
        
        complianceTags.add(new Tag()
            .withKey(RETENTION_KEY)
            .withValue(retentionPeriod)); // "1Year", "3Years", "7Years", "Indefinite"
        
        complianceTags.add(new Tag()
            .withKey(COMPLIANCE_KEY)
            .withValue(String.join(",", frameworks))); // "SOX", "GDPR", "HIPAA", "PCI"
        
        complianceTags.add(new Tag()
            .withKey(REVIEWED_KEY)
            .withValue(java.time.LocalDate.now().toString()));
        
        TagResourceRequest complianceRequest = new TagResourceRequest()
            .withSecretId(secretId)
            .withTags(complianceTags);
        
        try {
            client.tagResource(complianceRequest);
            System.out.println("Compliance tags applied to: " + secretId);
        } catch (Exception e) {
            System.err.println("Failed to apply compliance tags: " + e.getMessage());
        }
    }
    
    public void auditComplianceTags() {
        ListSecretsRequest listRequest = new ListSecretsRequest();
        ListSecretsResult listResult = client.listSecrets(listRequest);
        
        System.out.println("Compliance Audit Report:");
        System.out.println("========================");
        
        for (SecretListEntry secret : listResult.getSecretList()) {
            boolean hasClassification = false;
            boolean hasRetention = false;
            boolean hasCompliance = false;
            
            if (secret.getTags() != null) {
                for (Tag tag : secret.getTags()) {
                    switch (tag.getKey()) {
                        case CLASSIFICATION_KEY:
                            hasClassification = true;
                            break;
                        case RETENTION_KEY:
                            hasRetention = true;
                            break;
                        case COMPLIANCE_KEY:
                            hasCompliance = true;
                            break;
                    }
                }
            }
            
            System.out.println("Secret: " + secret.getName());
            System.out.println("  Classification: " + (hasClassification ? "✓" : "✗"));
            System.out.println("  Retention: " + (hasRetention ? "✓" : "✗"));
            System.out.println("  Compliance: " + (hasCompliance ? "✓" : "✗"));
            
            if (!hasClassification || !hasRetention || !hasCompliance) {
                System.out.println("  STATUS: NON-COMPLIANT");
            }
            System.out.println();
        }
    }
}

Automated Tag Management

public class AutomatedTagManager {
    
    public void enforceTaggingStandards(String secretId) {
        try {
            DescribeSecretResult secret = client.describeSecret(
                new DescribeSecretRequest().withSecretId(secretId));
            
            List<Tag> currentTags = secret.getTags();
            List<Tag> requiredTags = new ArrayList<>();
            
            // Check and add missing required tags
            if (!hasTag(currentTags, "Environment")) {
                // Infer environment from secret name
                String environment = inferEnvironmentFromName(secret.getName());
                requiredTags.add(new Tag().withKey("Environment").withValue(environment));
            }
            
            if (!hasTag(currentTags, "CreatedBy")) {
                requiredTags.add(new Tag().withKey("CreatedBy").withValue("AutomatedTagging"));
            }
            
            if (!hasTag(currentTags, "CreatedDate")) {
                requiredTags.add(new Tag().withKey("CreatedDate")
                    .withValue(secret.getCreatedDate().toString()));
            }
            
            if (!requiredTags.isEmpty()) {
                TagResourceRequest tagRequest = new TagResourceRequest()
                    .withSecretId(secretId)
                    .withTags(requiredTags);
                
                client.tagResource(tagRequest);
                System.out.println("Applied missing tags to: " + secretId);
            }
            
        } catch (Exception e) {
            System.err.println("Failed to enforce tagging standards: " + e.getMessage());
        }
    }
    
    private boolean hasTag(List<Tag> tags, String key) {
        if (tags == null) return false;
        return tags.stream().anyMatch(tag -> key.equals(tag.getKey()));
    }
    
    private String inferEnvironmentFromName(String secretName) {
        String lowerName = secretName.toLowerCase();
        if (lowerName.contains("prod")) return "Production";
        if (lowerName.contains("dev")) return "Development";
        if (lowerName.contains("test")) return "Testing";
        if (lowerName.contains("stage")) return "Staging";
        return "Unknown";
    }
}

Error Handling

Common policy and tagging exceptions:

try {
    PutResourcePolicyResult result = client.putResourcePolicy(request);
} catch (MalformedPolicyDocumentException e) {
    System.err.println("Invalid policy document: " + e.getMessage());
} catch (PublicPolicyException e) {
    System.err.println("Policy allows public access (blocked): " + e.getMessage());
} catch (InvalidParameterException e) {
    System.err.println("Invalid policy or tag parameter: " + e.getMessage());
} catch (LimitExceededException e) {
    System.err.println("Tag limit exceeded: " + e.getMessage());
} catch (ResourceNotFoundException e) {
    System.err.println("Resource not found: " + e.getMessage());
} catch (AWSSecretsManagerException e) {
    System.err.println("Service error: " + e.getMessage());
}

Best Practices

Policy Management

  1. Least Privilege: Grant minimal necessary permissions
  2. Regular Review: Audit policies periodically
  3. Validation: Always validate policies before applying
  4. Documentation: Document policy purpose and conditions
  5. Testing: Test policies in non-production environments

Tagging Strategy

  1. Standardization: Define organization-wide tagging standards
  2. Automation: Use automated tagging for consistency
  3. Cost Allocation: Use tags for billing and cost tracking
  4. Compliance: Tag for regulatory and audit requirements
  5. Lifecycle: Include creation and review dates in tags
  6. Searchability: Use consistent naming conventions
  7. Limits: Stay within AWS tag limits (50 tags per resource)
  8. Access Control: Use tags in IAM policies for fine-grained access

Install with Tessl CLI

npx tessl i tessl/maven-com-amazonaws--aws-java-sdk-secretsmanager

docs

index.md

policies-tags.md

replication.md

rotation.md

secret-management.md

utilities.md

tile.json