Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ eureka.client.fetch-registry=true
eureka.instance.hostname=eureka-server
eureka.client.serviceUrl.defaultZone=http://eureka-server:8761/eureka

jwt.secretKey = f2b21eeadc7f3693dbc373dca5f49400293d722eb955353c11250b9367cd1635
jwt.secretKey = 0dbe57fd2165cd78d6da1d118028a1fd3b60cb06e8d331f42f59d75be65a857d
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ eureka.client.fetch-registry=true
eureka.instance.hostname=eureka-server
eureka.client.serviceUrl.defaultZone=http://eureka-server:8761/eureka

jwt.secretKey = f2b21eeadc7f3693dbc373dca5f49400293d722eb955353c11250b9367cd1635
jwt.secretKey = 0dbe57fd2165cd78d6da1d118028a1fd3b60cb06e8d331f42f59d75be65a857d
2 changes: 1 addition & 1 deletion auth-service/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ spring.jpa.properties.hibernate.format_sql=true



jwt.secretKey = f2b21eeadc7f3693dbc373dca5f49400293d722eb955353c11250b9367cd1635
jwt.secretKey = 0dbe57fd2165cd78d6da1d118028a1fd3b60cb06e8d331f42f59d75be65a857d
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class ResourceManagementURI {
public static final String test = "/test";
public static final String INMONTHANDCLASS = "/in-month-and-class";
public static final String MATERIAL_TYPE = "/material-type";
public static final String MATERIAL = "/material-type";
public static final String MATERIAL = "/material";
public static final String SESSION_ID = "/{sessionId}";
public static final String MATERIAL_ID = "/{materialId}";
public static final String CLASS_ID = "/{classId}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ server.servlet.context-path=/
#springdoc.swagger-ui.urls[1].url=/dms-mediator/v3/api-docs
#springdoc.swagger-ui.urls[1].display-name=dms-mediator

jwt.secretKey = f2b21eeadc7f3693dbc373dca5f49400293d722eb955353c11250b9367cd1635
jwt.secretKey = 0dbe57fd2165cd78d6da1d118028a1fd3b60cb06e8d331f42f59d75be65a857d

# eureka
eureka.client.register-with-eureka=true
Expand Down
2 changes: 1 addition & 1 deletion lms-gateway/src/main/resources/application-kube.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ server.servlet.context-path=/
#springdoc.swagger-ui.urls[1].url=/dms-mediator/v3/api-docs
#springdoc.swagger-ui.urls[1].display-name=dms-mediator

jwt.secretKey = f2b21eeadc7f3693dbc373dca5f49400293d722eb955353c11250b9367cd1635
jwt.secretKey = 0dbe57fd2165cd78d6da1d118028a1fd3b60cb06e8d331f42f59d75be65a857d

#linkered
spring.cloud.gateway.discovery.locator.enabled=true
Expand Down
2 changes: 1 addition & 1 deletion lms-gateway/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ logging.level.org.springframework.cloud.gateway.handler.RoutePredicateHandlerMap
#springdoc.swagger-ui.urls[1].url=/dms-mediator/v3/api-docs
#springdoc.swagger-ui.urls[1].display-name=dms-mediator

jwt.secretKey = f2b21eeadc7f3693dbc373dca5f49400293d722eb955353c11250b9367cd1635
jwt.secretKey = 0dbe57fd2165cd78d6da1d118028a1fd3b60cb06e8d331f42f59d75be65a857d

# eureka
eureka.client.register-with-eureka=true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ eureka.client.fetch-registry=true
eureka.instance.hostname=eureka-server
eureka.client.serviceUrl.defaultZone=http://eureka-server:8761/eureka

jwt.secretKey = f2b21eeadc7f3693dbc373dca5f49400293d722eb955353c11250b9367cd1635
jwt.secretKey = 0dbe57fd2165cd78d6da1d118028a1fd3b60cb06e8d331f42f59d75be65a857d

# payhere
payhere.merchentSecretCode=YOUR_MERCHANT_SECRET_KEY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ eureka.client.fetch-registry=true
eureka.instance.hostname=eureka-server
eureka.client.serviceUrl.defaultZone=http://eureka-server:8761/eureka

jwt.secretKey = f2b21eeadc7f3693dbc373dca5f49400293d722eb955353c11250b9367cd1635
jwt.secretKey = 0dbe57fd2165cd78d6da1d118028a1fd3b60cb06e8d331f42f59d75be65a857d

# payhere
payhere.merchentSecretCode=YOUR_MERCHANT_SECRET_KEY
Expand Down
2 changes: 1 addition & 1 deletion payment-service/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ eureka.client.fetch-registry=true
eureka.instance.hostname=localhost
eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka

jwt.secretKey = f2b21eeadc7f3693dbc373dca5f49400293d722eb955353c11250b9367cd1635
jwt.secretKey = 0dbe57fd2165cd78d6da1d118028a1fd3b60cb06e8d331f42f59d75be65a857d

# payhere
payhere.merchentSecretCode=YOUR_MERCHANT_SECRET_KEY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ eureka.client.registerWithEureka=true
eureka.client.fetchRegistry=true
eureka.instance.hostname=localhost

jwt.secretKey = f2b21eeadc7f3693dbc373dca5f49400293d722eb955353c11250b9367cd1635
jwt.secretKey = 0dbe57fd2165cd78d6da1d118028a1fd3b60cb06e8d331f42f59d75be65a857d

Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public AppResponse<String> deleteMaterial(@PathVariable UUID materialId) {
}
}

@GetMapping(ResourceManagementURI.MATERIAL + URIPrefix.GET_VIDEO_Signed_Url)
@PostMapping (ResourceManagementURI.MATERIAL + URIPrefix.GET_VIDEO_Signed_Url)
public AppResponse<String> getVideoMaterialSignedUrl(@RequestBody AppRequest<SignedUrlRequest> request) {
try {
String s = materialService.getVideoMaterialSignedUrl(request.getData());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ eureka.client.registerWithEureka=true
eureka.client.fetchRegistry=true
eureka.instance.hostname=eureka-server

jwt.secretKey = f2b21eeadc7f3693dbc373dca5f49400293d722eb955353c11250b9367cd1635
jwt.secretKey = 0dbe57fd2165cd78d6da1d118028a1fd3b60cb06e8d331f42f59d75be65a857d
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ eureka.client.registerWithEureka=true
eureka.client.fetchRegistry=true
eureka.instance.hostname=eureka-server

jwt.secretKey = f2b21eeadc7f3693dbc373dca5f49400293d722eb955353c11250b9367cd1635
jwt.secretKey = 0dbe57fd2165cd78d6da1d118028a1fd3b60cb06e8d331f42f59d75be65a857d
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,4 @@ eureka.client.registerWithEureka=true
eureka.client.fetchRegistry=true
eureka.instance.hostname=localhost

jwt.secretKey = f2b21eeadc7f3693dbc373dca5f49400293d722eb955353c11250b9367cd1635
jwt.secretKey = 0dbe57fd2165cd78d6da1d118028a1fd3b60cb06e8d331f42f59d75be65a857d
11 changes: 11 additions & 0 deletions resource-management/resource-management-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk18on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
<version>1.78.1</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>cloudfront</artifactId>
<version>2.29.15</version>
</dependency>
</dependencies>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,33 @@
import com.itgura.request.MaterialRequest;
import com.itgura.request.SignedUrlRequest;
import com.itgura.request.dto.UserResponseDto;
import com.itgura.response.dto.MaterialResponseDto;
import com.itgura.response.dto.SessionResponseDto;
import com.itgura.response.dto.mapper.MaterialMapper;
import com.itgura.response.dto.mapper.SessionMapper;
import com.itgura.service.MaterialService;
import com.itgura.service.UserDetailService;
import com.itgura.util.UserUtil;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.ForbiddenException;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import software.amazon.awssdk.services.cloudfront.CloudFrontUtilities;
import software.amazon.awssdk.services.cloudfront.internal.utils.SigningUtils;
import software.amazon.awssdk.services.cloudfront.model.CannedSignerRequest;
import software.amazon.awssdk.services.cloudfront.model.CustomSignerRequest;
import software.amazon.awssdk.services.cloudfront.url.SignedUrl;

import javax.security.auth.login.CredentialNotFoundException;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Security;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.*;


Expand Down Expand Up @@ -157,34 +161,76 @@ public String deleteMaterial(UUID materialId) throws ApplicationException, Crede
@Override
public String getVideoMaterialSignedUrl(SignedUrlRequest signedUrlRequest) throws Exception {

long expirationTime = Instant.now().getEpochSecond() + (signedUrlRequest.getExpiresInHours() * 3600L);
CloudFrontUtilities cloudFrontUtilities = CloudFrontUtilities.create();
Instant expirationDate = Instant.ofEpochSecond(Instant.now().getEpochSecond() + (signedUrlRequest.getExpiresInHours() * 3600L));

// Define policy with IP restriction and expiration time
String policy = String.format(
"{\"Statement\":[{\"Resource\":\"%s/%s\",\"Condition\":{\"DateLessThan\":{\"AWS:EpochTime\":%d},\"IpAddress\":{\"AWS:SourceIp\":\"%s\"}}}]}",
cloudFrontDomain, signedUrlRequest.getFilePath(), expirationTime, signedUrlRequest.getUserIpAddress());
// Base64 encode the policy
String base64EncodedPolicy = Base64.getEncoder().encodeToString(policy.getBytes());

// Sign the policy with the private key
String signature = signPolicyWithPrivateKey(base64EncodedPolicy);
CustomSignerRequest customSignerRequest = CustomSignerRequest.builder()
.resourceUrl(cloudFrontDomain + "/" + signedUrlRequest.getFilePath())
.expirationDate(expirationDate)
.ipRange(signedUrlRequest.getUserIpAddress())
.keyPairId(keyPairId)
.privateKey(new ClassPathResource(privateKeyPath).getFile().toPath())
.build();
SignedUrl signedUrl = cloudFrontUtilities.getSignedUrlWithCustomPolicy(customSignerRequest);
return signedUrl.url();


// Construct the signed URL
return String.format("%s/%s?Policy=%s&Signature=%s&Key-Pair-Id=%s",
cloudFrontDomain, signedUrlRequest.getFilePath(),
urlEncode(base64EncodedPolicy),
urlEncode(signature),
keyPairId);

// long expirationTime = Instant.now().getEpochSecond() + (signedUrlRequest.getExpiresInHours() * 3600L);
//
// // Define policy with IP restriction and expiration time
// String policy = String.format(
// "{\"Statement\":[{\"Resource\":\"%s/%s\",\"Condition\":{\"DateLessThan\":{\"AWS:EpochTime\":%d},\"IpAddress\":{\"AWS:SourceIp\":\"%s\"}}}]}",
// cloudFrontDomain, signedUrlRequest.getFilePath(), expirationTime, signedUrlRequest.getUserIpAddress());
//
//// String policy = String.format(
//// "{\"Statement\":[{\"Resource\":\"%s/%s\"}]}",
//// cloudFrontDomain, signedUrlRequest.getFilePath());
// System.out.println("policy: "+policy);
// // Base64 encode the policy
// String base64EncodedPolicy = Base64.getEncoder().encodeToString(policy.getBytes());
//
// String decodedPolicy = new String(Base64.getDecoder().decode(base64EncodedPolicy));
// System.out.println("Decoded Policy: " + decodedPolicy);
//
// // Sign the policy with the private key
// String signature = signPolicyWithPrivateKey(base64EncodedPolicy);
// System.out.println("Signature: "+signature);
//
//
// // Construct the signed URL
// return String.format("%s/%s?Policy=%s&Signature=%s&Key-Pair-Id=%s",
// cloudFrontDomain, signedUrlRequest.getFilePath(),
// urlEncode(base64EncodedPolicy),
// urlEncode(signature),
// keyPairId);

}

private String signPolicyWithPrivateKey(String base64EncodedPolicy) throws Exception {
byte[] privateKeyBytes = Files.readAllBytes(Paths.get(privateKeyPath));
// Add the Bouncy Castle provider
Security.addProvider(new BouncyCastleProvider());

ClassPathResource resource = new ClassPathResource(privateKeyPath);
byte[] privateKeyBytes = Files.readAllBytes(resource.getFile().toPath());

// // Convert to string and strip PEM markers
// String privateKeyContent = new String(privateKeyBytes);
// privateKeyContent = privateKeyContent
// .replace("-----BEGIN PRIVATE KEY-----", "")
// .replace("-----END PRIVATE KEY-----", "")
// .replaceAll("\\s+", ""); // Remove all whitespace
//
// // Decode Base64 content
// byte[] decodedKey = Base64.getDecoder().decode(privateKeyContent);


// Generate the private key
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
PrivateKey privateKey = java.security.KeyFactory.getInstance("RSA").generatePrivate(keySpec);
PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);

Signature signature = Signature.getInstance("SHA1withRSA");
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(base64EncodedPolicy.getBytes());
byte[] signedBytes = signature.sign();
Expand All @@ -194,6 +240,7 @@ private String signPolicyWithPrivateKey(String base64EncodedPolicy) throws Excep


private String urlEncode(String value) {

return value.replace("+", "-").replace("=", "_").replace("/", "~");
}

Expand Down Expand Up @@ -227,4 +274,41 @@ private String urlEncode(String value) {
//
// }
// }



public String generateCustomSignedUrl(String resourcePath, Instant activeDate, Instant expirationDate, String ipAddress) throws Exception {
// Load private key
PrivateKey privateKey = loadPrivateKey();

// Build custom policy
String resourceUrl = cloudFrontDomain + "/" + resourcePath;
String customPolicy = SigningUtils.buildCustomPolicyForSignedUrl(resourceUrl, activeDate, expirationDate, ipAddress);
System.out.println("Custom Policy: " + customPolicy);

// Sign the policy
byte[] signatureBytes = SigningUtils.signWithSha1Rsa(customPolicy.getBytes(), privateKey);
String urlSafeSignature = SigningUtils.makeBytesUrlSafe(signatureBytes);

// Base64 encode the policy
String base64EncodedPolicy = Base64.getEncoder().encodeToString(customPolicy.getBytes());

// Construct the signed URL
return String.format("%s/%s?Policy=%s&Signature=%s&Key-Pair-Id=%s",
cloudFrontDomain,
resourcePath,
urlSafeEncode(base64EncodedPolicy),
urlSafeSignature,
keyPairId);
}

private PrivateKey loadPrivateKey() throws Exception {
byte[] privateKeyBytes = Files.readAllBytes(Paths.get(privateKeyPath));
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
return KeyFactory.getInstance("RSA").generatePrivate(keySpec);
}

private String urlSafeEncode(String value) {
return value.replace("+", "-").replace("=", "_").replace("/", "~");
}
}
Loading