Skip to content

Service Accounts - Fleet integration #70724

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

Merged
merged 16 commits into from
Mar 31, 2021
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
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

[role="xpack"]
[[security-api-get-builtin-privileges]]
=== Get builtin privileges API
Expand Down Expand Up @@ -83,6 +84,7 @@ A successful call returns an object with "cluster" and "index" fields.
"manage_rollup",
"manage_saml",
"manage_security",
"manage_service_account",
"manage_slm",
"manage_token",
"manage_transform",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.core.security.action.service;

import org.elasticsearch.action.ActionType;

public class CreateServiceAccountTokenAction extends ActionType<CreateServiceAccountTokenResponse> {

public static final String NAME = "cluster:admin/xpack/security/service_account/token/create";
public static final CreateServiceAccountTokenAction INSTANCE = new CreateServiceAccountTokenAction();

private CreateServiceAccountTokenAction() {
super(NAME, CreateServiceAccountTokenResponse::new);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.core.security.action.service;

import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;

import java.io.IOException;
import java.util.Objects;

import static org.elasticsearch.action.ValidateActions.addValidationError;

public class CreateServiceAccountTokenRequest extends ActionRequest {

private final String namespace;
private final String serviceName;
private final String tokenName;
private WriteRequest.RefreshPolicy refreshPolicy = WriteRequest.RefreshPolicy.WAIT_UNTIL;

public CreateServiceAccountTokenRequest(String namespace, String serviceName, String tokenName) {
this.namespace = namespace;
this.serviceName = serviceName;
this.tokenName = tokenName;
}

public CreateServiceAccountTokenRequest(StreamInput in) throws IOException {
super(in);
this.namespace = in.readString();
this.serviceName = in.readString();
this.tokenName = in.readString();
this.refreshPolicy = WriteRequest.RefreshPolicy.readFrom(in);
}

public String getNamespace() {
return namespace;
}

public String getServiceName() {
return serviceName;
}

public String getTokenName() {
return tokenName;
}

public WriteRequest.RefreshPolicy getRefreshPolicy() {
return refreshPolicy;
}

public void setRefreshPolicy(WriteRequest.RefreshPolicy refreshPolicy) {
this.refreshPolicy = Objects.requireNonNull(refreshPolicy, "refresh policy may not be null");
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
CreateServiceAccountTokenRequest that = (CreateServiceAccountTokenRequest) o;
return Objects.equals(namespace, that.namespace) && Objects.equals(serviceName, that.serviceName)
&& Objects.equals(tokenName, that.tokenName) && refreshPolicy == that.refreshPolicy;
}

@Override
public int hashCode() {
return Objects.hash(namespace, serviceName, tokenName, refreshPolicy);
}

@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeString(namespace);
out.writeString(serviceName);
out.writeString(tokenName);
refreshPolicy.writeTo(out);
}

@Override
public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null;
if (Strings.isNullOrEmpty(namespace)) {
validationException = addValidationError("service account namespace is required", validationException);
}

if (Strings.isNullOrEmpty(serviceName)) {
validationException = addValidationError("service account service-name is required", validationException);
}

if (Strings.isNullOrEmpty(tokenName)) {
validationException = addValidationError("service account token name is required", validationException);
} else {
if (tokenName.length() > 256) {
validationException = addValidationError(
"service account token name may not be more than 256 characters long", validationException);
}
if (tokenName.equals(tokenName.trim()) == false) {
validationException = addValidationError(
"service account token name may not begin or end with whitespace", validationException);
}
if (tokenName.startsWith("_")) {
validationException = addValidationError(
"service account token name may not begin with an underscore", validationException);
}
}
return validationException;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.core.security.action.service;

import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;

import java.io.IOException;
import java.util.Objects;

public class CreateServiceAccountTokenResponse extends ActionResponse implements ToXContentObject {

@Nullable
private final String name;
@Nullable
private final SecureString value;

private CreateServiceAccountTokenResponse(boolean created, String name, SecureString value) {
this.name = name;
this.value = value;
}

public CreateServiceAccountTokenResponse(StreamInput in) throws IOException {
super(in);
this.name = in.readOptionalString();
this.value = in.readOptionalSecureString();
}

public String getName() {
return name;
}

public SecureString getValue() {
return value;
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject()
.field("created", true)
.field("token")
.startObject()
.field("name", name)
.field("value", value.toString())
.endObject()
.endObject();
return builder;
}

@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeOptionalString(name);
out.writeOptionalSecureString(value);
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
CreateServiceAccountTokenResponse that = (CreateServiceAccountTokenResponse) o;
return Objects.equals(name, that.name) && Objects.equals(value, that.value);
}

@Override
public int hashCode() {
return Objects.hash(name, value);
}

public static CreateServiceAccountTokenResponse created(String name, SecureString value) {
return new CreateServiceAccountTokenResponse(true, name, value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.core.security.action.service;

import org.elasticsearch.action.ActionType;

public class GetServiceAccountTokensAction extends ActionType<GetServiceAccountTokensResponse> {

public static final String NAME = "cluster:admin/xpack/security/service_account/token/get";
public static final GetServiceAccountTokensAction INSTANCE = new GetServiceAccountTokensAction();

public GetServiceAccountTokensAction() {
super(NAME, GetServiceAccountTokensResponse::new);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.core.security.action.service;

import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;

import java.io.IOException;
import java.util.Objects;

import static org.elasticsearch.action.ValidateActions.addValidationError;

public class GetServiceAccountTokensRequest extends ActionRequest {

private final String namespace;
private final String serviceName;

public GetServiceAccountTokensRequest(String namespace, String serviceName) {
this.namespace = namespace;
this.serviceName = serviceName;
}

public GetServiceAccountTokensRequest(StreamInput in) throws IOException {
super(in);
this.namespace = in.readString();
this.serviceName = in.readString();
}

public String getNamespace() {
return namespace;
}

public String getServiceName() {
return serviceName;
}

@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
GetServiceAccountTokensRequest that = (GetServiceAccountTokensRequest) o;
return Objects.equals(namespace, that.namespace) && Objects.equals(serviceName, that.serviceName);
}

@Override
public int hashCode() {
return Objects.hash(namespace, serviceName);
}

@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeString(namespace);
out.writeString(serviceName);
}

@Override
public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null;
if (Strings.isNullOrEmpty(namespace)) {
validationException = addValidationError("service account namespace is required", validationException);
}

if (Strings.isNullOrEmpty(serviceName)) {
validationException = addValidationError("service account service-name is required", validationException);
}
return validationException;
}
}
Loading