Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions proto/redpanda/core/admin/v2/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,12 @@ proto_library(
srcs = ["security.proto"],
visibility = ["//visibility:public"],
deps = [
"//proto/redpanda/core/common/v1:security_types_proto",
"//proto/redpanda/core/pbgen:options_proto",
"//proto/redpanda/core/pbgen:rpc_proto",
"@googleapis//google/api:field_behavior_proto",
"@googleapis//google/api:resource_proto",
"@protobuf//:field_mask_proto",
"@protobuf//:timestamp_proto",
],
)
Expand All @@ -117,6 +119,8 @@ redpanda_proto_library(
],
visibility = ["//visibility:public"],
deps = [
"//proto/redpanda/core/common/v1:security_types_redpanda_proto",
"//src/v/serde/protobuf:field_mask",
"@abseil-cpp//absl/time:time",
],
)
150 changes: 150 additions & 0 deletions proto/redpanda/core/admin/v2/security.proto
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,68 @@ syntax = "proto3";

package redpanda.core.admin.v2;

import "proto/redpanda/core/common/v1/security_types.proto";
import "proto/redpanda/core/pbgen/options.proto";
import "proto/redpanda/core/pbgen/rpc.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/field_mask.proto";

option (pbgen.cpp_namespace) = "proto::admin";

// The SecurityService provides security-related operations.
service SecurityService {
// CreateScramCredential
//
// Create a SCRAM credential.
rpc CreateScramCredential(CreateScramCredentialRequest)
returns (CreateScramCredentialResponse) {
option (pbgen.rpc) = {
authz: SUPERUSER
};
}

// GetScramCredential
//
// Retrieve a SCRAM credential.
rpc GetScramCredential(GetScramCredentialRequest)
returns (GetScramCredentialResponse) {
option (pbgen.rpc) = {
authz: SUPERUSER
};
}

// ListScramCredentials
//
// List all SCRAM credentials.
rpc ListScramCredentials(ListScramCredentialsRequest)
returns (ListScramCredentialsResponse) {
option (pbgen.rpc) = {
authz: SUPERUSER
};
}

// UpdateScramCredential
//
// Update a SCRAM credential.
rpc UpdateScramCredential(UpdateScramCredentialRequest)
returns (UpdateScramCredentialResponse) {
option (pbgen.rpc) = {
authz: SUPERUSER
};
}

// DeleteScramCredential
//
// Delete a SCRAM credential.
rpc DeleteScramCredential(DeleteScramCredentialRequest)
returns (DeleteScramCredentialResponse) {
option (pbgen.rpc) = {
authz: SUPERUSER
};
}

// CreateRole
//
// Create a new Role resource.
Expand Down Expand Up @@ -134,6 +186,27 @@ service SecurityService {
/* Resources */
// =============================================

// The ScramCredential resource used for SCRAM authentication.
message ScramCredential {
option (google.api.resource) = {
type: "redpanda.core.admin.SecurityService/ScramCredential"
pattern: "scram_credentials/{scram_credential}"
};

// The name of the SCRAM credential.
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.field_behavior) = IMMUTABLE
];

// The SCRAM mechanism used for this credential.
redpanda.core.common.v1.ScramMechanism mechanism = 2;

// The password for the SCRAM credential.
string password = 3
[debug_redact = true, (google.api.field_behavior) = INPUT_ONLY];
Comment on lines +205 to +207
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should also add a password_set_at field (a, la

// Timestamp of when the password was last set - only valid if password_set
// is true
google.protobuf.Timestamp password_set_at = 4
[(google.api.field_behavior) = OUTPUT_ONLY];
). This is so processes that are attempting to reconcile can have a signal as to when was the last time the password was changed.

I do think this may result in having to make controller updates to store the timestamp.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, this was part of the original mini rfc but omitted it in this change to try to minimize/isolate the controller changes. Discussed this and decided to split this off to a separate follow-on task (CORE-15278).

}

// The Role resource represents a security role with associated members.
message Role {
option (google.api.resource) = {
Expand All @@ -155,6 +228,83 @@ message Role {
/* RPC Requests and Responses */
// =============================================

// CreateScramCredentialRequest is the request for the CreateScramCredential
// RPC.
message CreateScramCredentialRequest {
// The SCRAM credential to create.
ScramCredential scram_credential = 1
[(google.api.field_behavior) = REQUIRED];
}

// CreateScramCredentialResponse is the response from the CreateScramCredential
// RPC.
message CreateScramCredentialResponse {
// The created SCRAM credential.
ScramCredential scram_credential = 1;
}

// GetScramCredentialRequest is the request for the GetScramCredential RPC.
message GetScramCredentialRequest {
// The name of the SCRAM credential to retrieve.
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {
type: "redpanda.core.admin.SecurityService/ScramCredential"
}
];
}

// GetScramCredentialResponse is the response from the GetScramCredential RPC.
message GetScramCredentialResponse {
// The requested SCRAM credential.
ScramCredential scram_credential = 1;
}

// ListScramCredentialsRequest is the request for the ListScramCredentials RPC.
message ListScramCredentialsRequest {}

// ListScramCredentialsResponse is the response from the ListScramCredentials
// RPC.
message ListScramCredentialsResponse {
// The list of SCRAM credentials.
repeated ScramCredential scram_credentials = 1;
}

// UpdateScramCredentialRequest is the request for the UpdateScramCredential
// RPC.
message UpdateScramCredentialRequest {
// The SCRAM credential to update.
ScramCredential scram_credential = 1
[(google.api.field_behavior) = REQUIRED];

// The list of fields to update
// See [AIP-134](https://google.aip.dev/134) for how to use `field_mask`
google.protobuf.FieldMask update_mask = 2;
}

// UpdateScramCredentialResponse is the response from the UpdateScramCredential
// RPC.
message UpdateScramCredentialResponse {
// The updated SCRAM credential.
ScramCredential scram_credential = 1;
}

// DeleteScramCredentialRequest is the request for the DeleteScramCredential
// RPC.
message DeleteScramCredentialRequest {
// The name of the SCRAM credential to delete.
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {
type: "redpanda.core.admin.SecurityService/ScramCredential"
}
];
}

// DeleteScramCredentialResponse is the response from the DeleteScramCredential
// RPC.
message DeleteScramCredentialResponse {}

// CreateRoleRequest is the request for the CreateRole RPC.
message CreateRoleRequest {
// The Role to create.
Expand Down
13 changes: 13 additions & 0 deletions proto/redpanda/core/common/v1/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,16 @@ redpanda_proto_library(
protos = [":tls_proto"],
visibility = ["//visibility:public"],
)

proto_library(
name = "security_types_proto",
srcs = ["security_types.proto"],
visibility = ["//visibility:public"],
deps = ["//proto/redpanda/core/pbgen:options_proto"],
)

redpanda_proto_library(
name = "security_types_redpanda_proto",
protos = [":security_types_proto"],
visibility = ["//visibility:public"],
)
30 changes: 30 additions & 0 deletions proto/redpanda/core/common/v1/security_types.proto
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider just changing the file name to security.proto

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2026 Redpanda Data, Inc.
//
// 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.

syntax = "proto3";

package redpanda.core.common.v1;

import "proto/redpanda/core/pbgen/options.proto";

option (pbgen.cpp_namespace) = "proto::common";

// Valid SCRAM mechanisms
enum ScramMechanism {
SCRAM_MECHANISM_UNSPECIFIED = 0;
// SCRAM-SHA-256
SCRAM_MECHANISM_SCRAM_SHA_256 = 1;
// SCRAM-SHA-512
SCRAM_MECHANISM_SCRAM_SHA_512 = 2;
}
Loading
Loading