/*
Copyright 2025 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// To regenerate api.pb.go run `hack/update-codegen.sh protobindings`
syntax = "proto3";

package v1;

option go_package = "k8s.io/externaljwt/apis/v1";

import "google/protobuf/timestamp.proto";

// This service is served by a process on a local Unix Domain Socket.
service ExternalJWTSigner {
    // Sign takes a serialized JWT payload, and returns the serialized header and
    // signature. The caller can then assemble the JWT from the header, payload,
    // and signature. Signature can be generated by signing 
    // `base64url(header) + "." + base64url(payload)` with signing key.
    //
    // The plugin MUST set a key id in the returned JWT header.
    rpc Sign(SignJWTRequest) returns (SignJWTResponse) {}
  
    // FetchKeys returns the set of public keys that are trusted to sign
    // Kubernetes service account tokens. Kube-apiserver will call this RPC:
    //
    // * Every time it tries to validate a JWT from the service account issuer with an unknown key ID, and
    //
    // * Periodically, so it can serve reasonably-up-to-date keys from the OIDC
    //   JWKs endpoint.
    rpc FetchKeys(FetchKeysRequest) returns (FetchKeysResponse) {}
    
    // Metadata is meant to be called once on startup.
    // Enables sharing metadata with kube-apiserver (eg: the max token lifetime that signer supports)
    rpc Metadata(MetadataRequest) returns (MetadataResponse) {}
  }
  
  message SignJWTRequest {
    // URL-safe base64 wrapped payload to be signed.
    // Exactly as it appears in the second segment of the JWT
    string claims = 1;
  }
  
  message SignJWTResponse {
    // header must contain only alg, kid, typ claims.
    // typ must be “JWT”.
    // kid must be non-empty, <=1024 characters, and its corresponding public key should not be excluded from OIDC discovery.
    // alg must be one of the algorithms supported by kube-apiserver (currently RS256, ES256, ES384, ES512).
    // header cannot have any additional data that kube-apiserver does not recognize.
    // Already wrapped in URL-safe base64, exactly as it appears in the first segment of the JWT.
    string header = 1;
  
    // The signature for the JWT.
    // Already wrapped in URL-safe base64, exactly as it appears in the final segment of the JWT.
    string signature = 2;
  }
  
  message FetchKeysRequest {}
  
  message FetchKeysResponse {
    repeated Key keys = 1;
  
    // The timestamp when this data was pulled from the authoritative source of
    // truth for verification keys.
    // kube-apiserver can export this from metrics, to enable end-to-end SLOs.
    google.protobuf.Timestamp data_timestamp = 2;
  
    // refresh interval for verification keys to pick changes if any.
    // any value <= 0 is considered a misconfiguration.
    int64 refresh_hint_seconds = 3;
  }
  
  message Key {
    // A unique identifier for this key.
    // Length must be <=1024.
    string key_id = 1;
  
    // The public key, PKIX-serialized.
    // must be a public key supported by kube-apiserver (currently RSA 256 or ECDSA 256/384/521)
    bytes key = 2;
  
    // Set only for keys that are not used to sign bound tokens.
    // eg: supported keys for legacy tokens.
    // If set, key is used for verification but excluded from OIDC discovery docs.
    // if set, external signer should not use this key to sign a JWT.
    bool exclude_from_oidc_discovery = 3;
  }
  
  message MetadataRequest {}
  
  message MetadataResponse {
    // used by kube-apiserver for defaulting/validation of JWT lifetime while accounting for configuration flag values:
    // 1. `--service-account-max-token-expiration`
    // 2. `--service-account-extend-token-expiration`
    //
    // * If `--service-account-max-token-expiration` is greater than `max_token_expiration_seconds`, kube-apiserver treats that as misconfiguration and exits.
    // * If `--service-account-max-token-expiration` is not explicitly set, kube-apiserver defaults to `max_token_expiration_seconds`.
    // * If `--service-account-extend-token-expiration` is true, the extended expiration is `min(1 year, max_token_expiration_seconds)`.
    //
    // `max_token_expiration_seconds` must be at least 600s.
    int64 max_token_expiration_seconds = 1;
  }