Skip to content

Commit

Permalink
Finish basic K8S access check
Browse files Browse the repository at this point in the history
This checks K8S api access by asking whoami (a la `kubectl auth whoami`).

Also adds Tokio as a dependency. The kube crate is all async, and so we need
Tokio to deal with that.

Signed-off-by: Robert Detjens <[email protected]>
  • Loading branch information
detjensrobert committed Jun 19, 2024
1 parent f47d852 commit abdc650
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 4 deletions.
13 changes: 13 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ fully_pub = "0.1.4"
# kubernetes:
kube = { version = "0.91.0", features = ["runtime", "derive"] }
k8s-openapi = { version = "0.22.0", features = ["latest"] }
tokio = { version = "1.38.0", features = ["rt", "macros"] }
41 changes: 37 additions & 4 deletions src/access_handlers/kube.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,56 @@
use anyhow::{Error, Result};
use anyhow::{anyhow, Error, Result};
use k8s_openapi::api::{
authentication::v1::SelfSubjectReview, authorization::v1::SelfSubjectAccessReview,
};
use k8s_openapi::serde_json::{from_value, json, to_string};
use kube;
use simplelog::*;
use tokio;

use crate::configparser::{config, CONFIG};

/// kubernetes access checks
pub fn check(profile: &config::ProfileConfig) -> Result<()> {
#[tokio::main(flavor = "current_thread")] // make this a sync function
pub async fn check(profile: &config::ProfileConfig) -> Result<()> {
// we need to make sure that:
// a) can talk to the cluster
// b) have the right permissions (a la `kubectl auth can-i`)

// build a client
let client = client(profile);
let client = client(profile).await?;

// try to get cluster info (whoami)
let reviewapi: kube::Api<SelfSubjectReview> = kube::Api::all(client);
let resp = reviewapi
.create(
&kube::api::PostParams::default(),
&from_value(json!({
"apiVersion": "authentication.k8s.io/v1",
"kind": "SelfSubjectReview"
}))?,
)
.await?;
let status = resp.status.ok_or(anyhow!("could not access cluster"))?;

// todo: Is it safe to unwrap here? Does this always return a username?
// Seems like it but need to test more... dont want to panic
debug!(
"authenticated as {:?}",
status
.user_info
.unwrap()
.username
.unwrap_or("(no username)".into())
);

// todo:? check what permissions we have and error if we are missing any

return Ok(());
}

/// Returns K8S Client for selected profile
async fn client(profile: &config::ProfileConfig) -> Result<kube::Client> {
// make sure the profile exists
debug!("building kube client");

// read in kubeconfig from given kubeconfig (or default)
// (use kube::Config to specify context)
Expand Down

0 comments on commit abdc650

Please sign in to comment.