-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(chart/service)!: add Authorization (#74)
Signed-off-by: Sebastian Becker <[email protected]>
- Loading branch information
Showing
35 changed files
with
1,883 additions
and
268 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
amphora-service/src/main/java/io/carbynestack/amphora/service/config/AuthProperties.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* | ||
* Copyright (c) 2024 - for information on the respective copyright owner | ||
* see the NOTICE file and/or the repository https://github.com/carbynestack/amphora. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.carbynestack.amphora.service.config; | ||
|
||
import lombok.Data; | ||
import lombok.experimental.Accessors; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
import org.springframework.stereotype.Component; | ||
|
||
@ConfigurationProperties(prefix = "carbynestack.auth") | ||
@Component | ||
@Data | ||
@Accessors(chain = true) | ||
public class AuthProperties { | ||
private String userIdFieldName; | ||
} |
31 changes: 31 additions & 0 deletions
31
amphora-service/src/main/java/io/carbynestack/amphora/service/config/OpaConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
* Copyright (c) 2024 - for information on the respective copyright owner | ||
* see the NOTICE file and/or the repository https://github.com/carbynestack/amphora. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.carbynestack.amphora.service.config; | ||
|
||
import io.carbynestack.amphora.service.opa.JwtReader; | ||
import io.carbynestack.amphora.service.opa.OpaClient; | ||
import java.net.URI; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
@Configuration | ||
public class OpaConfig { | ||
|
||
@Bean | ||
JwtReader jwtReader(AuthProperties authProperties) { | ||
return new JwtReader(authProperties.getUserIdFieldName()); | ||
} | ||
|
||
@Bean | ||
OpaClient opaClient(OpaProperties opaProperties) { | ||
return OpaClient.builder() | ||
.opaServiceUri(URI.create(opaProperties.getEndpoint())) | ||
.defaultPolicyPackage(opaProperties.getDefaultPolicyPackage()) | ||
.build(); | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
amphora-service/src/main/java/io/carbynestack/amphora/service/config/OpaProperties.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/* | ||
* Copyright (c) 2024 - for information on the respective copyright owner | ||
* see the NOTICE file and/or the repository https://github.com/carbynestack/amphora. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
package io.carbynestack.amphora.service.config; | ||
|
||
import lombok.Data; | ||
import lombok.experimental.Accessors; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
import org.springframework.stereotype.Component; | ||
|
||
@ConfigurationProperties(prefix = "carbynestack.opa") | ||
@Component | ||
@Data | ||
@Accessors(chain = true) | ||
public class OpaProperties { | ||
|
||
private String endpoint; | ||
private String defaultPolicyPackage; | ||
} |
14 changes: 14 additions & 0 deletions
14
amphora-service/src/main/java/io/carbynestack/amphora/service/exceptions/CsOpaException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/* | ||
* Copyright (c) 2024 - for information on the respective copyright owner | ||
* see the NOTICE file and/or the repository https://github.com/carbynestack/amphora. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.carbynestack.amphora.service.exceptions; | ||
|
||
public class CsOpaException extends Exception { | ||
public CsOpaException(String message) { | ||
super(message); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
...rvice/src/main/java/io/carbynestack/amphora/service/exceptions/UnauthorizedException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/* | ||
* Copyright (c) 2024 - for information on the respective copyright owner | ||
* see the NOTICE file and/or the repository https://github.com/carbynestack/amphora. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.carbynestack.amphora.service.exceptions; | ||
|
||
public class UnauthorizedException extends Exception { | ||
public UnauthorizedException(String message) { | ||
super(message); | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
amphora-service/src/main/java/io/carbynestack/amphora/service/opa/JwtReader.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
* Copyright (c) 2024 - for information on the respective copyright owner | ||
* see the NOTICE file and/or the repository https://github.com/carbynestack/amphora. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.carbynestack.amphora.service.opa; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import io.carbynestack.amphora.service.exceptions.UnauthorizedException; | ||
import io.vavr.control.Option; | ||
import java.util.Base64; | ||
|
||
public class JwtReader { | ||
static ObjectMapper mapper = new ObjectMapper(); | ||
private final String userIdField; | ||
|
||
public JwtReader(String userIdField) { | ||
this.userIdField = userIdField; | ||
} | ||
|
||
public String extractUserIdFromAuthHeader(String header) throws UnauthorizedException { | ||
return extractFieldFromAuthHeader(header, userIdField); | ||
} | ||
|
||
private static String extractFieldFromAuthHeader(String header, String field) | ||
throws UnauthorizedException { | ||
return tokenFromHeader(header) | ||
.flatMap(JwtReader::dataNodeFromToken) | ||
.flatMap(node -> fieldFromNode(node, field)) | ||
.getOrElseThrow(() -> new UnauthorizedException("No token provided")); | ||
} | ||
|
||
private static Option<JsonNode> dataNodeFromToken(String token) { | ||
String[] parts = token.split("\\."); | ||
if (parts.length != 3) { | ||
return Option.none(); | ||
} | ||
try { | ||
String jwt = new String(Base64.getDecoder().decode(parts[1])); | ||
return Option.of(mapper.reader().readTree(jwt)); | ||
} catch (JsonProcessingException e) { | ||
return Option.none(); | ||
} | ||
} | ||
|
||
private static Option<String> tokenFromHeader(String header) { | ||
if (header != null && header.startsWith("Bearer ")) { | ||
return Option.of(header.substring(7)); | ||
} | ||
return Option.none(); | ||
} | ||
|
||
private static Option<String> fieldFromNode(JsonNode node, String fieldName) { | ||
JsonNode field = node; | ||
try { | ||
for (String f : fieldName.split("\\.")) { | ||
field = field.get(f); | ||
} | ||
return Option.of(field.asText()); | ||
} catch (NullPointerException e) { | ||
return Option.none(); | ||
} | ||
} | ||
} |
63 changes: 63 additions & 0 deletions
63
amphora-service/src/main/java/io/carbynestack/amphora/service/opa/OpaClient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/* | ||
* Copyright (c) 2024 - for information on the respective copyright owner | ||
* see the NOTICE file and/or the repository https://github.com/carbynestack/amphora. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.carbynestack.amphora.service.opa; | ||
|
||
import io.carbynestack.amphora.common.Tag; | ||
import io.carbynestack.httpclient.CsHttpClient; | ||
import io.carbynestack.httpclient.CsHttpClientException; | ||
import java.net.URI; | ||
import java.util.List; | ||
import lombok.Builder; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
@Slf4j | ||
public class OpaClient { | ||
private final CsHttpClient<String> csHttpClient; | ||
private final URI opaServiceUri; | ||
private final String defaultPolicyPackage; | ||
|
||
@Builder | ||
public OpaClient(URI opaServiceUri, String defaultPolicyPackage) { | ||
this(CsHttpClient.createDefault(), opaServiceUri, defaultPolicyPackage); | ||
} | ||
|
||
OpaClient(CsHttpClient<String> httpClient, URI opaServiceUri, String defaultPolicyPackage) { | ||
this.csHttpClient = httpClient; | ||
this.opaServiceUri = opaServiceUri; | ||
this.defaultPolicyPackage = defaultPolicyPackage; | ||
} | ||
|
||
/** | ||
* Evaluate the OPA policy package with the given action, subject and tags. | ||
* | ||
* @param policyPackage The OPA policy package to evaluate. | ||
* @param action The action to evaluate. | ||
* @param subject The subject attempting to perform the action. | ||
* @param tags The tags describing the accessed object. | ||
* @return True if the subject can perform the action, false otherwise (or if an error occurred). | ||
*/ | ||
public boolean isAllowed(String policyPackage, String action, String subject, List<Tag> tags) { | ||
OpaRequestBody body = OpaRequestBody.builder().subject(subject).tags(tags).build(); | ||
try { | ||
return csHttpClient | ||
.postForObject( | ||
opaServiceUri.resolve( | ||
String.format("/v1/data/%s/%s", policyPackage.replace(".", "/"), action)), | ||
new OpaRequest(body), | ||
OpaResult.class) | ||
.isAllowed(); | ||
} catch (CsHttpClientException e) { | ||
log.error("Error occurred while evaluating OPA policy package", e); | ||
} | ||
return false; | ||
} | ||
|
||
public OpaClientRequest newRequest() { | ||
return new OpaClientRequest(this, defaultPolicyPackage); | ||
} | ||
} |
43 changes: 43 additions & 0 deletions
43
amphora-service/src/main/java/io/carbynestack/amphora/service/opa/OpaClientRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/* | ||
* Copyright (c) 2024 - for information on the respective copyright owner | ||
* see the NOTICE file and/or the repository https://github.com/carbynestack/amphora. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.carbynestack.amphora.service.opa; | ||
|
||
import io.carbynestack.amphora.common.Tag; | ||
import io.carbynestack.amphora.service.exceptions.CsOpaException; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import lombok.Setter; | ||
import lombok.experimental.Accessors; | ||
import org.apache.logging.log4j.util.Strings; | ||
|
||
@Setter() | ||
@Accessors(chain = true, fluent = true) | ||
public class OpaClientRequest { | ||
private String withPolicyPackage; | ||
private String withSubject; | ||
private List<Tag> withTags; | ||
private String withAction; | ||
|
||
private final OpaClient opaClient; | ||
|
||
public OpaClientRequest(OpaClient opaClient, String defaultPolicyPackage) { | ||
this.withPolicyPackage = defaultPolicyPackage; | ||
this.opaClient = opaClient; | ||
} | ||
|
||
public boolean evaluate() throws CsOpaException { | ||
if (Strings.isEmpty(withSubject)) { | ||
throw new CsOpaException("Subject is required to evaluate the policy"); | ||
} | ||
if (Strings.isEmpty(withAction)) { | ||
throw new CsOpaException("Action is required to evaluate the policy"); | ||
} | ||
withTags.removeIf(Objects::isNull); | ||
return opaClient.isAllowed(withPolicyPackage, withAction, withSubject, withTags); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
amphora-service/src/main/java/io/carbynestack/amphora/service/opa/OpaRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* | ||
* Copyright (c) 2024 - for information on the respective copyright owner | ||
* see the NOTICE file and/or the repository https://github.com/carbynestack/amphora. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.carbynestack.amphora.service.opa; | ||
|
||
import lombok.Getter; | ||
|
||
@Getter | ||
class OpaRequest { | ||
OpaRequestBody input; | ||
|
||
public OpaRequest(OpaRequestBody input) { | ||
this.input = input; | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
amphora-service/src/main/java/io/carbynestack/amphora/service/opa/OpaRequestBody.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright (c) 2024 - for information on the respective copyright owner | ||
* see the NOTICE file and/or the repository https://github.com/carbynestack/amphora. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.carbynestack.amphora.service.opa; | ||
|
||
import io.carbynestack.amphora.common.Tag; | ||
import java.util.List; | ||
import lombok.Builder; | ||
import lombok.Value; | ||
|
||
@Value | ||
public class OpaRequestBody { | ||
String subject; | ||
List<Tag> tags; | ||
|
||
@Builder | ||
public OpaRequestBody(String subject, List<Tag> tags) { | ||
this.subject = subject; | ||
this.tags = tags; | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
amphora-service/src/main/java/io/carbynestack/amphora/service/opa/OpaResult.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* | ||
* Copyright (c) 2024 - for information on the respective copyright owner | ||
* see the NOTICE file and/or the repository https://github.com/carbynestack/amphora. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package io.carbynestack.amphora.service.opa; | ||
|
||
import lombok.Setter; | ||
|
||
public class OpaResult { | ||
@Setter private boolean result; | ||
|
||
boolean isAllowed() { | ||
return result; | ||
} | ||
} |
Oops, something went wrong.