/** * Construct a LFS repository storing large objects in Amazon S3 * * @param config * AWS S3 storage bucket configuration */ public S3Repository(S3Config config) { validateConfig(config); this.s3Config = config; }
private static byte[] createSignature(S3Config bucketConfig, String dateTimeStamp, String dateStamp, String scope, String canonicalRequest) { String stringToSign = stringToSign(SCHEME, ALGORITHM, dateTimeStamp, scope, canonicalRequest); byte[] signature = (SCHEME + bucketConfig.getSecretKey()) .getBytes(UTF_8); signature = sign(dateStamp, signature); signature = sign(bucketConfig.getRegion(), signature); signature = sign(S3, signature); signature = sign(TERMINATOR, signature); signature = sign(stringToSign, signature); return signature; } }
private void validateConfig(S3Config config) { assertNotEmpty(LfsServerText.get().undefinedS3AccessKey, config.getAccessKey()); assertNotEmpty(LfsServerText.get().undefinedS3Bucket, config.getBucket()); assertNotEmpty(LfsServerText.get().undefinedS3Region, config.getRegion()); assertNotEmpty(LfsServerText.get().undefinedS3SecretKey, config.getSecretKey()); assertNotEmpty(LfsServerText.get().undefinedS3StorageClass, config.getStorageClass()); }
@Override public Response.Action getUploadAction(AnyLongObjectId oid, long size) { cacheObjectMetaData(oid, size); URL objectUrl = getObjectUrl(oid); Map<String, String> headers = new HashMap<String, String>(); headers.put(X_AMZ_CONTENT_SHA256, oid.getName()); headers.put(HDR_CONTENT_LENGTH, Long.toString(size)); headers.put(X_AMZ_STORAGE_CLASS, s3Config.getStorageClass()); headers.put(HttpSupport.HDR_CONTENT_TYPE, "application/octet-stream"); //$NON-NLS-1$ headers = SignerV4.createHeaderAuthorization(s3Config, objectUrl, METHOD_PUT, headers, oid.getName()); Response.Action a = new Response.Action(); a.href = objectUrl.toString(); a.header = new HashMap<>(); a.header.putAll(headers); return a; }
@Override public Response.Action getDownloadAction(AnyLongObjectId oid) { URL endpointUrl = getObjectUrl(oid); Map<String, String> queryParams = new HashMap<String, String>(); queryParams.put(X_AMZ_EXPIRES, Integer.toString(s3Config.getExpirationSeconds())); Map<String, String> headers = new HashMap<String, String>(); String authorizationQueryParameters = SignerV4.createAuthorizationQuery( s3Config, endpointUrl, METHOD_GET, headers, queryParams, UNSIGNED_PAYLOAD); Response.Action a = new Response.Action(); a.href = endpointUrl.toString() + "?" + authorizationQueryParameters; //$NON-NLS-1$ return a; }
private URL getObjectUrl(AnyLongObjectId oid) { try { return new URL(String.format("https://s3-%s.amazonaws.com/%s/%s", //$NON-NLS-1$ s3Config.getRegion(), s3Config.getBucket(), getPath(oid))); } catch (MalformedURLException e) { throw new IllegalArgumentException(MessageFormat.format( LfsServerText.get().unparsableEndpoint, e.getMessage())); } }
private static String formatAuthorizationHeader( S3Config bucketConfig, String canonicalizedHeaderNames, String scope, byte[] signature) { StringBuilder s = new StringBuilder(); s.append(SCHEME).append("-").append(ALGORITHM).append(" "); //$NON-NLS-1$ //$NON-NLS-2$ s.append("Credential=").append(bucketConfig.getAccessKey()).append("/") //$NON-NLS-1$//$NON-NLS-2$ .append(scope).append(","); //$NON-NLS-1$ s.append("SignedHeaders=").append(canonicalizedHeaderNames).append(","); //$NON-NLS-1$ //$NON-NLS-2$ s.append("Signature=").append(toHex(signature)); //$NON-NLS-1$ return s.toString(); }
private static String canonicalRequest(URL endpoint, String httpMethod, String queryParameters, String canonicalizedHeaderNames, String canonicalizedHeaders, String bodyHash) { return String.format("%s\n%s\n%s\n%s\n%s\n%s", //$NON-NLS-1$ httpMethod, canonicalizeResourcePath(endpoint), queryParameters, canonicalizedHeaders, canonicalizedHeaderNames, bodyHash); }
private static String formatAuthorizationQuery( Map<String, String> queryParameters) { StringBuilder s = new StringBuilder(); for (String key : queryParameters.keySet()) { appendQuery(s, key, queryParameters.get(key)); } return s.toString(); }
private static String canonicalizeResourcePath(URL endpoint) { if (endpoint == null) { return "/"; //$NON-NLS-1$ } String path = endpoint.getPath(); if (path == null || path.isEmpty()) { return "/"; //$NON-NLS-1$ } String encodedPath = urlEncode(path, true); if (encodedPath.startsWith("/")) { //$NON-NLS-1$ return encodedPath; } else { return "/" + encodedPath; //$NON-NLS-1$ } }
private void validateConfig(S3Config config) { assertNotEmpty(LfsServerText.get().undefinedS3AccessKey, config.getAccessKey()); assertNotEmpty(LfsServerText.get().undefinedS3Bucket, config.getBucket()); assertNotEmpty(LfsServerText.get().undefinedS3Region, config.getRegion()); assertNotEmpty(LfsServerText.get().undefinedS3SecretKey, config.getSecretKey()); assertNotEmpty(LfsServerText.get().undefinedS3StorageClass, config.getStorageClass()); }
private static byte[] createSignature(S3Config bucketConfig, String dateTimeStamp, String dateStamp, String scope, String canonicalRequest) { String stringToSign = stringToSign(SCHEME, ALGORITHM, dateTimeStamp, scope, canonicalRequest); byte[] signature = (SCHEME + bucketConfig.getSecretKey()).getBytes(); signature = sign(dateStamp, signature); signature = sign(bucketConfig.getRegion(), signature); signature = sign(S3, signature); signature = sign(TERMINATOR, signature); signature = sign(stringToSign, signature); return signature; } }
/** {@inheritDoc} */ @Override public Response.Action getDownloadAction(AnyLongObjectId oid) { URL endpointUrl = getObjectUrl(oid); Map<String, String> queryParams = new HashMap<>(); queryParams.put(X_AMZ_EXPIRES, Integer.toString(s3Config.getExpirationSeconds())); Map<String, String> headers = new HashMap<>(); String authorizationQueryParameters = SignerV4.createAuthorizationQuery( s3Config, endpointUrl, METHOD_GET, headers, queryParams, UNSIGNED_PAYLOAD); Response.Action a = new Response.Action(); a.href = endpointUrl.toString() + "?" + authorizationQueryParameters; //$NON-NLS-1$ return a; }
private URL getObjectUrl(AnyLongObjectId oid) { try { return new URL(String.format("https://s3-%s.amazonaws.com/%s/%s", //$NON-NLS-1$ s3Config.getRegion(), s3Config.getBucket(), getPath(oid))); } catch (MalformedURLException e) { throw new IllegalArgumentException(MessageFormat.format( LfsServerText.get().unparsableEndpoint, e.getMessage())); } }
private static String formatAuthorizationHeader( S3Config bucketConfig, String canonicalizedHeaderNames, String scope, byte[] signature) { StringBuilder s = new StringBuilder(); s.append(SCHEME).append("-").append(ALGORITHM).append(" "); //$NON-NLS-1$ //$NON-NLS-2$ s.append("Credential=").append(bucketConfig.getAccessKey()).append("/") //$NON-NLS-1$//$NON-NLS-2$ .append(scope).append(","); //$NON-NLS-1$ s.append("SignedHeaders=").append(canonicalizedHeaderNames).append(","); //$NON-NLS-1$ //$NON-NLS-2$ s.append("Signature=").append(toHex(signature)); //$NON-NLS-1$ return s.toString(); }
/** * Construct a LFS repository storing large objects in Amazon S3 * * @param config * AWS S3 storage bucket configuration */ public S3Repository(S3Config config) { validateConfig(config); this.s3Config = config; }
private static String canonicalRequest(URL endpoint, String httpMethod, String queryParameters, String canonicalizedHeaderNames, String canonicalizedHeaders, String bodyHash) { return String.format("%s\n%s\n%s\n%s\n%s\n%s", //$NON-NLS-1$ httpMethod, canonicalizeResourcePath(endpoint), queryParameters, canonicalizedHeaders, canonicalizedHeaderNames, bodyHash); }
private static String formatAuthorizationQuery( Map<String, String> queryParameters) { StringBuilder s = new StringBuilder(); for (String key : queryParameters.keySet()) { appendQuery(s, key, queryParameters.get(key)); } return s.toString(); }