Skip to content

Commit

Permalink
Adding support for authentik and an example
Browse files Browse the repository at this point in the history
  • Loading branch information
sebt3 committed Jun 10, 2024
1 parent 0e2ed96 commit bf6cb8a
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 65 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "kuberest"
version = "0.9.0"
version = "0.9.1"
authors = ["Sébastien Huss <[email protected]>"]
edition = "2021"
default-run = "controller"
Expand Down
4 changes: 2 additions & 2 deletions charts/kuberest/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ apiVersion: v2
name: kuberest
description: Allow to Control remote REST api endpoints from the confort of your cluster
type: application
version: 0.2.1
appVersion: "0.9.0"
version: "0.9.1"
appVersion: "0.9.1"
2 changes: 1 addition & 1 deletion charts/kuberest/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ tracing:
port: 4317

networkPolicy:
enabled: true
enabled: false
dns: true
# apiserver access: please scope; take addresses from "kubectl get endpoints kubernetes -n default"
apiserver:
Expand Down
4 changes: 4 additions & 0 deletions deploy/crd/crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,10 @@ spec:
description: 'keyName: the key of the object (default: id)'
nullable: true
type: string
keyUseSlash:
description: 'keyUseSlash: should the update/delete url end with a slash at the end (default: false)'
nullable: true
type: boolean
name:
description: 'name of the write (used for handlebars renders: write.<name>)'
type: string
Expand Down
58 changes: 4 additions & 54 deletions deploy/operator/deployment.yaml
Original file line number Diff line number Diff line change
@@ -1,54 +1,4 @@
---
# Source: kuberest/templates/networkpolicy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: kuberest
namespace: default
labels:
app: kuberest
app.kubernetes.io/name: kuberest
app.kubernetes.io/version: "0.9.0"
spec:
podSelector:
matchLabels:
app: kuberest
policyTypes:
- Ingress
- Egress
egress:

# Kubernetes apiserver access
- to:
- ipBlock:
cidr: 0.0.0.0/0
ports:
- port: 443
protocol: TCP
- port: 6443
protocol: TCP
# DNS egress
- to:
- podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- port: 53
protocol: UDP

ingress:
# prometheus metrics scraping support
- from:
- namespaceSelector:
matchLabels:
name: monitoring
podSelector:
matchLabels:
app: prometheus
ports:
- port: http
protocol: TCP
---
# Source: kuberest/templates/rbac.yaml
# Scoped service account
apiVersion: v1
Expand All @@ -58,7 +8,7 @@ metadata:
labels:
app: kuberest
app.kubernetes.io/name: kuberest
app.kubernetes.io/version: "0.9.0"
app.kubernetes.io/version: "0.9.1"
namespace: default
automountServiceAccountToken: true
---
Expand Down Expand Up @@ -104,7 +54,7 @@ metadata:
labels:
app: kuberest
app.kubernetes.io/name: kuberest
app.kubernetes.io/version: "0.9.0"
app.kubernetes.io/version: "0.9.1"
spec:
type: ClusterIP
ports:
Expand All @@ -124,7 +74,7 @@ metadata:
labels:
app: kuberest
app.kubernetes.io/name: kuberest
app.kubernetes.io/version: "0.9.0"
app.kubernetes.io/version: "0.9.1"
spec:
replicas: 1
selector:
Expand All @@ -142,7 +92,7 @@ spec:
{}
containers:
- name: kuberest
image: sebt3/kuberest:0.9.0
image: sebt3/kuberest:0.9.1
imagePullPolicy: IfNotPresent
securityContext:
{}
Expand Down
96 changes: 96 additions & 0 deletions examples/authentik/openid-gitea.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
apiVersion: kuberest.solidite.fr/v1
kind: RestEndPoint
metadata:
name: openid-gitea
spec:
inputs:
- name: output
secretRef:
optional: true
name: gitea-openid
- name: uuid
handleBarsRender: "{{#if input.output.data.key }}{{ base64_decode input.output.data.key }}{{else}}{{ uuid_new_v7 }}{{/if}}"
- name: admin
secretRef:
name: authentik
client:
baseurl: "http://authentik.{{ input.admin.metadata.namespace }}.svc/api/v3"
keyName: pk
headers:
Authorization: "Bearer {{ base64_decode input.admin.data.AUTHENTIK_BOOTSTRAP_TOKEN }}"
reads:
- name: keypair
path: crypto/certificatekeypairs
items:
- name: ak
key: "?name=authentik+Self-signed+Certificate"
- name: flow
path: flows/instances
items:
- name: authorization
key: default-provider-authorization-implicit-consent/
- name: default
key: default-authentication-flow/
- name: scopes
path: propertymappings/scope
items:
- name: email
key: "?scope_name=email"
- name: profile
key: "?scope_name=profile"
- name: openid
key: "?scope_name=openid"
writes:
- name: oauth
path: providers/oauth2
keyUseSlash: true
items:
- name: gitea
values: |-
name: gitea-app
authorization_flow: "{{ read.flow.authorization.pk }}"
authentication_flow: "{{ read.flow.default.pk }}"
client_id: "{{ input.uuid }}"
property_mappings:
- "{{ json_query "results[0].pk" read.scopes.email }}"
- "{{ json_query "results[0].pk" read.scopes.openid }}"
- "{{ json_query "results[0].pk" read.scopes.profile }}"
client_type: "confidential"
sub_mode: "user_username"
signing_key: "{{ json_query "results[0].pk" read.keypair.ak }}"
redirect_uris: "https://gitea.your-company.com/user/oauth2/authentik/callback"
- name: applications
path: core/applications
keyUseSlash: true
keyName: slug
items:
- name: gitea
values: |-
name: gitea-app
slug: gitea-app
provider: "{{ write.oauth.gitea.pk }}"
meta_launch_url: https://gitea.your-company.com
outputs:
- kind: ConfigMap
metadata:
name: project-list
data:
config.yaml: |-
name: gitea-app
authorization_flow: "{{ read.flow.authorization.pk }}"
authentication_flow: "{{ read.flow.default.pk }}"
client_id: "{{ input.uuid }}"
property_mappings:
- "{{ json_query "results[0].pk" read.scopes.email }}"
- "{{ json_query "results[0].pk" read.scopes.openid }}"
- "{{ json_query "results[0].pk" read.scopes.profile }}"
client_type: "confidential"
sub_mode: "user_username"
signing_key: "{{ json_query "results[0].pk" read.keypair.ak }}"
redirect_uris: "https://gitea.your-company.com/user/oauth2/authentik/callback"
- kind: Secret
metadata:
name: gitea-openid
data:
key: "{{ write.oauth.gitea.client_id }}"
secret: "{{ write.oauth.gitea.client_secret }}"
3 changes: 3 additions & 0 deletions src/httphandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,9 +474,12 @@ impl RestClient {
path: &str,
key: &str,
input: &Value,
use_slash: bool,
) -> Result<Value, Error> {
let full_path = if key == "" {
path.to_string()
} else if use_slash {
format!("{path}/{key}/")
} else {
format!("{path}/{key}")
};
Expand Down
45 changes: 39 additions & 6 deletions src/restendpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ pub struct WriteGroup {
pub path: String,
/// keyName: the key of the object (default: id)
pub key_name: Option<String>,
/// keyUseSlash: should the update/delete url end with a slash at the end (default: false)
pub key_use_slash: Option<bool>,
/// Method to use when creating an object (default: Get)
pub create_method: Option<CreateMethod>,
/// Method to use when reading an object (default: Post)
Expand Down Expand Up @@ -781,7 +783,13 @@ impl RestEndPoint {
rhai.set_dynamic("values", &values);

// Setup the httpClient
let mut rest = RestClient::new(self.spec.client.baseurl.clone().as_str());
let mut rest = RestClient::new(&template!(
self.spec.client.baseurl.clone().as_str(),
hbs,
&values,
conditions,
recorder
));
if let Some(headers) = self.spec.client.headers.clone() {
for (key, value) in headers {
rest.add_header(
Expand Down Expand Up @@ -1069,6 +1077,7 @@ impl RestEndPoint {
&path.as_str(),
&myself.key,
&vals,
group.key_use_slash.clone().unwrap_or(false),
)
.unwrap_or_else(|e| {
giveup = if let Error::MethodFailed(_, code, _) = e {
Expand Down Expand Up @@ -1128,6 +1137,12 @@ impl RestEndPoint {
}
} else {
// Create the object
let tmp = format!("{path}/");
let my_path = if group.key_use_slash.unwrap_or(false) {
tmp.as_str()
} else {
&path.as_str()
};
let obj = rest
.clone()
.obj_create(
Expand All @@ -1138,7 +1153,7 @@ impl RestEndPoint {
.clone()
.unwrap_or(CreateMethod::Post),
),
&path.as_str(),
&my_path,
&vals,
)
.unwrap_or_else(|e| {
Expand Down Expand Up @@ -1192,10 +1207,16 @@ impl RestEndPoint {
}).to_string()
}
};
if !giveup {
if !giveup && !key.is_empty() {
let tmp = format!("{key}/");
let my_key = if group.key_use_slash.unwrap_or(false) {
tmp.as_str()
} else {
&key.as_str()
};
target_new.push(OwnedRestPoint::new(
path.as_str(),
&key.as_str(),
my_key,
&group.name.as_str(),
&item.name.as_str(),
item.teardown.unwrap_or(
Expand Down Expand Up @@ -1910,7 +1931,13 @@ impl RestEndPoint {
rhai.set_dynamic("input", &values["input"]);
rhai.set_dynamic("values", &values);
// Setup the httpClient
let mut rest = RestClient::new(self.spec.client.baseurl.clone().as_str());
let mut rest = RestClient::new(&template!(
self.spec.client.baseurl.clone().as_str(),
hbs,
&values,
conditions,
recorder
));
if let Some(headers) = self.spec.client.headers.clone() {
for (key, value) in headers {
rest.add_header(
Expand Down Expand Up @@ -2079,7 +2106,13 @@ impl RestEndPoint {
}
}
}
if conditions.len() > 0 || owned_new.len() > 0 || target_new.len() > 0 {
if conditions.iter().any(|c| {
c.condition_type != ConditionsType::InputMissing
&& c.condition_type != ConditionsType::WriteAlreadyExist
&& c.condition_type != ConditionsType::OutputAlreadyExist
}) || owned_new.len() > 0
|| target_new.len() > 0
{
// Wait 30s before reporting the failure, because the controller keeps trying and it might hammer the api-server and the api-endpoint targeted otherwise. Beside the events generated already informed the user of the issue
tokio::task::block_in_place(|| {
tokio::runtime::Handle::current().block_on(async {
Expand Down

0 comments on commit bf6cb8a

Please sign in to comment.