All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.spiffe.spiffeid.SpiffeId Maven / Gradle / Ivy

Go to download

Core functionality to fetch, process and validate X.509 and JWT SVIDs and Bundles from the Workload API.

There is a newer version: 0.8.11
Show newest version
package io.spiffe.spiffeid;

import io.spiffe.exception.InvalidSpiffeIdException;
import lombok.NonNull;
import lombok.Value;
import org.apache.commons.lang3.StringUtils;

import static io.spiffe.spiffeid.TrustDomain.isValidTrustDomainChar;

/**
 * Represents a SPIFFE ID as defined in the SPIFFE standard.
 * 

* @see https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md */ @Value public class SpiffeId { static final String SPIFFE_SCHEME = "spiffe"; static final String SCHEME_PREFIX = SPIFFE_SCHEME + "://"; static final String EMPTY = "Cannot be empty"; static final String MISSING_TRUST_DOMAIN = "Trust domain is missing"; static final String WRONG_SCHEME = "Scheme is missing or invalid"; static final String BAD_TRUST_DOMAIN_CHAR = "Trust domain characters are limited to lowercase letters, numbers, dots, dashes, and underscores"; static final String BAD_PATH_SEGMENT_CHAR = "Path segment characters are limited to letters, numbers, dots, dashes, and underscores"; static final String DOT_SEGMENT = "Path cannot contain dot segments"; static final String EMPTY_SEGMENT = "Path cannot contain empty segments"; static final String TRAILING_SLASH = "Path cannot have a trailing slash"; TrustDomain trustDomain; String path; private SpiffeId(final TrustDomain trustDomain, final String path) { this.trustDomain = trustDomain; this.path = path; } /** * Returns a new SPIFFE ID in the given trust domain with joined * path segments. The path segments must be valid according to the SPIFFE * specification and must not contain path separators. * See https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE-ID.md#22-path * * @param trustDomain an instance of a {@link TrustDomain} * @param segments a list of string path segments * @return a {@link SpiffeId} * @throws InvalidSpiffeIdException if a given path segment contains an invalid char or empty or dot segment */ public static SpiffeId fromSegments(@NonNull final TrustDomain trustDomain, final String... segments) { StringBuilder path = new StringBuilder(); for (String p : segments) { validatePath(p); path.append('/'); path.append(p); } return new SpiffeId(trustDomain, path.toString()); } /** * Parses a SPIFFE ID from a string (e.g. spiffe://example.org/test). * * @param id a String representing a SPIFFE ID * @return A {@link SpiffeId} * @throws IllegalArgumentException if the given string is empty * @throws InvalidSpiffeIdException if the given string id contain an invalid scheme, invalid char or empty or dot segment */ public static SpiffeId parse(final String id) { if (StringUtils.isBlank(id)) { throw new IllegalArgumentException(EMPTY); } if (!id.contains(SCHEME_PREFIX)) { throw new InvalidSpiffeIdException(WRONG_SCHEME); } String rest = id.substring(SCHEME_PREFIX.length()); int i = 0; for (char c : rest.toCharArray()) { if (c == '/'){ break; } if (!isValidTrustDomainChar(c)) { throw new InvalidSpiffeIdException(BAD_TRUST_DOMAIN_CHAR); } i++; } if (i == 0) { throw new InvalidSpiffeIdException(MISSING_TRUST_DOMAIN); } String td = rest.substring(0, i); String path = rest.substring(i); if (StringUtils.isNotBlank(path)) { validatePath(path); } return new SpiffeId(new TrustDomain(td), path); } /** * Returns true if the trust domain of this SPIFFE ID is the same as trust domain given as parameter. * * @param trustDomain an instance of a {@link TrustDomain} * @return true if the given trust domain equals the trust domain of this object, * false otherwise */ public boolean memberOf(final TrustDomain trustDomain) { return this.trustDomain.equals(trustDomain); } /** * Returns the string representation of the SPIFFE ID, concatenating schema, trust domain, * and path segments (e.g. 'spiffe://example.org/path1/path2') */ @Override public String toString() { return String.format("%s://%s%s", SPIFFE_SCHEME, this.trustDomain.toString(), this.path); } /** * Validates that a path string is a conformant path for a SPIFFE ID. * See https://github.com/spiffe/spiffe/blob/main/standards/SPIFFE-ID.md#22-path */ public static void validatePath(String path) { if (StringUtils.isBlank(path)) { throw new IllegalArgumentException(EMPTY); } int segmentStart = 0; int segmentEnd = 0; for ( ; segmentEnd < path.length(); segmentEnd++) { char c = path.charAt(segmentEnd); if (c == '/') { switch (path.substring(segmentStart, segmentEnd)) { case "/": throw new InvalidSpiffeIdException(EMPTY_SEGMENT); case "/.": case "/..": throw new InvalidSpiffeIdException(DOT_SEGMENT); } segmentStart = segmentEnd; continue; } if (!isValidPathSegmentChar(c)) { throw new InvalidSpiffeIdException(BAD_PATH_SEGMENT_CHAR); } } switch (path.substring(segmentStart, segmentEnd)) { case "/": throw new InvalidSpiffeIdException(TRAILING_SLASH); case "/.": case "/..": throw new InvalidSpiffeIdException(DOT_SEGMENT); } } private static boolean isValidPathSegmentChar(char c) { if (c >= 'a' && c <= 'z') return true; if (c >= 'A' && c <= 'Z') return true; if (c >= '0' && c <= '9') return true; return c == '-' || c == '.' || c == '_'; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy