Skip to content

Commit

Permalink
Adding support for bcrypt hashes
Browse files Browse the repository at this point in the history
  • Loading branch information
sebt3 committed Dec 21, 2024
1 parent 9f279e7 commit 85b0439
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 22 deletions.
65 changes: 54 additions & 11 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "kuberest"
version = "1.1.4"
version = "1.1.5"
authors = ["Sébastien Huss <[email protected]>"]
edition = "2021"
default-run = "controller"
Expand Down Expand Up @@ -80,6 +80,7 @@ reqwest = { version = "0.12.4", features = ["rustls-tls"] }
base64 = "0.22.1"
rand = "0.8.5"
argon2 = { version = "0.5.3", features = ["std"] }
bcrypt = "0.16.0"

[dev-dependencies]
assert-json-diff = "2.0.2"
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: "1.1.4"
appVersion: "1.1.4"
version: "1.1.5"
appVersion: "1.1.5"
42 changes: 42 additions & 0 deletions charts/kuberest/templates/rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,45 @@ roleRef:
kind: ClusterRole
name: {{ include "controller.fullname" . }}
apiGroup: rbac.authorization.k8s.io
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
rbac.authorization.k8s.io/aggregate-to-view: 'true'
name: {{ include "controller.fullname" . }}:aggregate-to-view
rules:
- apiGroups: ["kuberest.solidite.fr"]
resources: ["restendpoints"]
verbs: ["get", "watch", "list"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
rbac.authorization.k8s.io/aggregate-to-edit: 'true'
name: {{ include "controller.fullname" . }}:aggregate-to-edit
rules:
- apiGroups: ["kuberest.solidite.fr"]
resources: ["restendpoints"]
verbs:
- patch
- update
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
rbac.authorization.k8s.io/aggregate-to-admin: 'true'
name: {{ include "controller.fullname" . }}:aggregate-to-admin
rules:
- apiGroups: ["kuberest.solidite.fr"]
resources: ["restendpoints/status"]
verbs:
- update
- apiGroups: ["kuberest.solidite.fr"]
resources: ["restendpoints"]
verbs:
- create
- delete
- deletecollection
53 changes: 49 additions & 4 deletions deploy/operator/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ metadata:
labels:
app: kuberest
app.kubernetes.io/name: kuberest
app.kubernetes.io/version: "1.1.4"
app.kubernetes.io/version: "1.1.5"
namespace: default
automountServiceAccountToken: true
---
Expand All @@ -33,6 +33,51 @@ rules:
verbs: ["create"]
---
# Source: kuberest/templates/rbac.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
rbac.authorization.k8s.io/aggregate-to-view: 'true'
name: kuberest:aggregate-to-view
rules:
- apiGroups: ["kuberest.solidite.fr"]
resources: ["restendpoints"]
verbs: ["get", "watch", "list"]
---
# Source: kuberest/templates/rbac.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
rbac.authorization.k8s.io/aggregate-to-edit: 'true'
name: kuberest:aggregate-to-edit
rules:
- apiGroups: ["kuberest.solidite.fr"]
resources: ["restendpoints"]
verbs:
- patch
- update
---
# Source: kuberest/templates/rbac.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
labels:
rbac.authorization.k8s.io/aggregate-to-admin: 'true'
name: kuberest:aggregate-to-admin
rules:
- apiGroups: ["kuberest.solidite.fr"]
resources: ["restendpoints/status"]
verbs:
- update
- apiGroups: ["kuberest.solidite.fr"]
resources: ["restendpoints"]
verbs:
- create
- delete
- deletecollection
---
# Source: kuberest/templates/rbac.yaml
# Binding the role to the account
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
Expand All @@ -57,7 +102,7 @@ metadata:
labels:
app: kuberest
app.kubernetes.io/name: kuberest
app.kubernetes.io/version: "1.1.4"
app.kubernetes.io/version: "1.1.5"
spec:
type: ClusterIP
ports:
Expand All @@ -77,7 +122,7 @@ metadata:
labels:
app: kuberest
app.kubernetes.io/name: kuberest
app.kubernetes.io/version: "1.1.4"
app.kubernetes.io/version: "1.1.5"
spec:
replicas: 1
selector:
Expand All @@ -95,7 +140,7 @@ spec:
{}
containers:
- name: kuberest
image: sebt3/kuberest:1.1.4
image: sebt3/kuberest:1.1.5
imagePullPolicy: IfNotPresent
securityContext:
{}
Expand Down
14 changes: 13 additions & 1 deletion src/handlebarshandler.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use crate::{hasheshandlers::Argon, passwordhandler::Passwords, Error, Result, RhaiRes};
use crate::{
hasheshandlers::{self, Argon},
passwordhandler::Passwords,
Error, Result, RhaiRes,
};
use base64::{engine::general_purpose::STANDARD, Engine as _};
use handlebars::{handlebars_helper, Handlebars};
use handlebars_misc_helpers::new_hbs;
Expand Down Expand Up @@ -33,6 +37,13 @@ handlebars_helper!(argon_hash: |password:Value| Argon::new().hash(password.as_st
warn!("handlebars::argon_hash failed to convert to string with: {e:?}");
String::new()
}));
handlebars_helper!(bcrypt_hash: |password:Value| hasheshandlers::bcrypt_hash(password.as_str().unwrap_or_else(|| {
warn!("handlebars::bcrypt_hash received a non-string password: {:?}",password);
""
}).to_string()).unwrap_or_else(|e| {
warn!("handlebars::bcrypt_hash failed to convert to string with: {e:?}");
String::new()
}));
handlebars_helper!(gen_password: |len:u32| Passwords::new().generate(len, 6, 2, 2));
handlebars_helper!(gen_password_alphanum: |len:u32| Passwords::new().generate(len, 8, 2, 0));

Expand All @@ -48,6 +59,7 @@ impl HandleBars<'_> {
engine.register_helper("base64_encode", Box::new(base64_encode));
engine.register_helper("header_basic", Box::new(header_basic));
engine.register_helper("argon_hash", Box::new(argon_hash));
engine.register_helper("bcrypt_hash", Box::new(bcrypt_hash));
engine.register_helper("gen_password", Box::new(gen_password));
engine.register_helper("gen_password_alphanum", Box::new(gen_password_alphanum));
// TODO: add more helpers
Expand Down
5 changes: 5 additions & 0 deletions src/hasheshandlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use argon2::{
password_hash::{rand_core::OsRng, PasswordHasher, SaltString},
Argon2,
};
use bcrypt::{hash, DEFAULT_COST};

#[derive(Clone, Debug)]
pub struct Argon {
Expand Down Expand Up @@ -36,3 +37,7 @@ impl Argon {
self.hash(password).map_err(rhai_err)
}
}

pub fn bcrypt_hash(password: String) -> Result<String> {
hash(&password, DEFAULT_COST).map_err(Error::BcryptError)
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ pub enum Error {
#[error("Argon2 password_hash error {0}")]
Argon2hash(#[from] argon2::password_hash::Error),

#[error("Bcrypt hash error {0}")]
BcryptError(#[from] bcrypt::BcryptError),

#[error("Unsupported method")]
UnsupportedMethod,

Expand Down
11 changes: 8 additions & 3 deletions src/restendpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1012,9 +1012,11 @@ impl RestEndPoint {
)
.unwrap_or_else(|e| {
conditions.push(ApplicationCondition::write_failed(&format!(
"Templating write.{}.{}.values raised {e:?}",
"Templating write.{}.{}.values \n{}\nusing values: \n{}\nraised {e:?}",
group.name.clone(),
item.name
item.name,
item.values.as_str(),
serde_yaml::to_string(&values).unwrap_or_default()
)));
json!({})
});
Expand Down Expand Up @@ -1583,7 +1585,10 @@ impl RestEndPoint {
} else if self.spec.teardown.is_none() {
// no teardown script, only prepare client if there are some write to delete
let status = self.status.clone().unwrap();
do_prepare_client = status.owned_target.is_empty();
do_prepare_client = !status.owned_target.is_empty();
}
if !do_prepare_client {
tracing::info!("Skipping to prepare the client");
}
let mut rhai = Script::new();
rhai.ctx.set_or_push("hbs", hbs.clone());
Expand Down
3 changes: 3 additions & 0 deletions src/rhaihandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ impl Script {
.register_fn("log_info", |s: ImmutableString| tracing::info!("{s}"))
.register_fn("log_warn", |s: ImmutableString| tracing::warn!("{s}"))
.register_fn("log_error", |s: ImmutableString| tracing::error!("{s}"))
.register_fn("bcrypt_hash", |s: ImmutableString| {
crate::hasheshandlers::bcrypt_hash(s.to_string()).map_err(rhai_err)
})
.register_fn("gen_password", |len: u32| -> String {
Passwords::new().generate(len, 6, 2, 2)
})
Expand Down

0 comments on commit 85b0439

Please sign in to comment.