Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Use securefmt to redact sensitive data #121

Open
rblaine95 opened this issue Jun 18, 2024 · 2 comments
Open

[Feature Request] Use securefmt to redact sensitive data #121

rblaine95 opened this issue Jun 18, 2024 · 2 comments

Comments

@rblaine95
Copy link

Hello, I've been using this library in an API I've been building and it's worked exceptionally well so far.

One of the crates I've been using is securefmt which redacts sensitive fields when I enable debug logging.

An example of using it:

use securefmt::Debug;

#[derive(Debug)]
struct SensitiveData {
    id: u8,
    #[sensitive]
    secret: u8
}

fn main() {
    println!("{:?}", SensitiveData { id: 1, secret: 42 })
}

Which will then output

SensitiveData { id: 1, secret: <redacted> }

I think it would be useful to add this to sensitive fields such as Client Secrets

@rblaine95 rblaine95 changed the title [Feature Request] Use securefmt to obfuscate sensitive data [Feature Request] Use securefmt to redact sensitive data Jun 18, 2024
@kilork
Copy link
Owner

kilork commented Jun 18, 2024

Hi @rblaine95!

It is interesting idea, thank you! I am currently trying to avoid Debug in structures with sensitive data, but this maybe a better option.

If we have such cases in generated code, this is a little bit more tricky, cause we need to know from OpenAPI description if this field is sensitive or provide extra configuration for such fields.

Could you maybe elaborate on which fields exactly should be [redacted] in Debug?

@rblaine95
Copy link
Author

rblaine95 commented Jun 19, 2024

Hi @kilork

One use case I've run into is the secret field in ClientRepresentation
In local development I realized I was debug logging the full ClientRepresentation and it included the secret:

let client = kc_client
    .realm_clients_post(
        "example-realm",
        ClientRepresentation {
            client_id: Some("example-client".to_string()),
            direct_access_grants_enabled: Some(true),
            name: Some("example-client".to_string()),
            public_client: Some(false),
            authorization_services_enabled: Some(true),
            service_accounts_enabled: Some(true),
            ..Default::default()
        },
    )
    .await
    .unwrap();
println!("{:#?}", client);

Which prints the following:

ClientRepresentation {
[... trim long output ...]
    client_authenticator_type: Some(
        "client-secret",
    ),
    client_id: Some(
        "example-client",
    ),
[... trim long output ...]
    secret: Some(
        "xeM3U1VMizbgCbIaVDHnqTkaoXkHe8FQ",
    ),
[... trim long output ...]
}

Scanning through the keycloak::types module, there are 6 structs with a secret field:

  • ApplicationRepresentation - pub secret: Option<TypeString>
  • ClientRepresentation - pub secret: Option<TypeString>
  • ConfigPropertyRepresentation - pub secret: Option<bool> - this probably doesn't need to be redacted 🤔
  • CredentialRepresentation - pub secret_data: Option<TypeString> and probably pub value: Option<TypeString> too because you can pass plaintext credentials in here to be hashed keycloak side
  • OAuthClientRepresentation - pub secret: Option<TypeString>
  • RealmRepresentation - pub code_secret: Option<TypeString> - which is deprecated anyways so might not need to worry about that

That's just searching for the word secret. There's probably more with other names (like value in CredentialRepresentation).

Scanning through the OpenAPI v3 Spec I don't really see anything about marking specific fields as sensitive.

However, one possible workaround could be for Keycloak to mark sensitive fields as password instead of string when generating their OpenAPI spec, maybe that can be used to hint "this is a sensitive string" when generating the Rust Client.

For example, from the Keycloak 25.0.0 OpenAPI Yaml :

openapi: 3.0.3
info:
  title: Keycloak Admin REST API
  description: This is a REST API reference for the Keycloak Admin REST API.
  version: "1.0"
[... trim unnecessary fields from very long doc...]
components:
  schemas:
    ClientRepresentation:
      properties:
        secret:
-          type: string
+          type: password

It looks like, unless Keycloak marks sensitive fields as sensitive when they generate their OpenAPI spec, there's potentially quite a bit of legwork to identify and mark all the sensitive fields.

A potential approach could be to have a list of known sensitive fields and to inject the #[sensitive] attribute after you've generated the Rust Client, maybe it can be added to the update.ts deno script?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants