All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.elasticsearch.client.security.user.privileges.IndicesPrivileges Maven / Gradle / Ivy

There is a newer version: 8.0.0-alpha2
Show newest version
/*
 * 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 and the Server Side Public License, v 1; you may not use this file except
 * in compliance with, at your election, the Elastic License 2.0 or the Server
 * Side Public License, v 1.
 */

package org.elasticsearch.client.security.user.privileges;

import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.xcontent.ConstructingObjectParser;
import org.elasticsearch.xcontent.ToXContentObject;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentType;

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

import static org.elasticsearch.xcontent.ConstructingObjectParser.constructorArg;
import static org.elasticsearch.xcontent.ConstructingObjectParser.optionalConstructorArg;

/**
 * Represents privileges over indices. There is a canonical set of privilege
 * names (eg. {@code IndicesPrivileges#READ_PRIVILEGE_NAME}) but there is
 * flexibility in the definition of finer grained, more specialized, privileges.
 * This also encapsulates field and document level security privileges. These
 * allow to control what fields or documents are readable or queryable.
 */
public final class IndicesPrivileges extends AbstractIndicesPrivileges implements ToXContentObject {

    @SuppressWarnings("unchecked")
    static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
        "indices_privileges",
        false,
        constructorObjects -> {
            int i = 0;
            final Collection indices = (Collection) constructorObjects[i++];
            final Collection privileges = (Collection) constructorObjects[i++];
            final boolean allowRestrictedIndices = (Boolean) constructorObjects[i++];
            final FieldSecurity fields = (FieldSecurity) constructorObjects[i++];
            final String query = (String) constructorObjects[i];
            return new IndicesPrivileges(indices, privileges, allowRestrictedIndices, fields, query);
        }
    );

    static {
        PARSER.declareStringArray(constructorArg(), NAMES);
        PARSER.declareStringArray(constructorArg(), PRIVILEGES);
        PARSER.declareBoolean(constructorArg(), ALLOW_RESTRICTED_INDICES);
        PARSER.declareObject(optionalConstructorArg(), FieldSecurity::parse, FIELD_PERMISSIONS);
        PARSER.declareStringOrNull(optionalConstructorArg(), QUERY);
    }

    private final FieldSecurity fieldSecurity;
    // missing query means all documents, i.e. no restrictions
    private final @Nullable String query;

    private IndicesPrivileges(
        Collection indices,
        Collection privileges,
        boolean allowRestrictedIndices,
        @Nullable FieldSecurity fieldSecurity,
        @Nullable String query
    ) {
        super(indices, privileges, allowRestrictedIndices);
        this.fieldSecurity = fieldSecurity;
        this.query = query;
    }

    /**
     * The combination of the {@link FieldSecurity#getGrantedFields() granted} and
     * {@link FieldSecurity#getDeniedFields() denied} document fields.
     * May be null, in which case no field level security is applicable, and all the document's fields are granted access to.
     */
    public FieldSecurity getFieldSecurity() {
        return fieldSecurity;
    }

    /**
     * A query limiting the visible documents in the indices. Can be null, in which
     * case all documents are visible.
     */
    public @Nullable String getQuery() {
        return this.query;
    }

    /**
     * If {@code true} some documents might not be visible. Only the documents
     * matching {@code query} will be readable.
     */
    @Override
    public boolean isUsingDocumentLevelSecurity() {
        return query != null;
    }

    /**
     * If {@code true} some document fields might not be visible.
     */
    @Override
    public boolean isUsingFieldLevelSecurity() {
        return fieldSecurity != null && fieldSecurity.isUsingFieldLevelSecurity();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        IndicesPrivileges that = (IndicesPrivileges) o;
        return indices.equals(that.indices)
            && privileges.equals(that.privileges)
            && allowRestrictedIndices == that.allowRestrictedIndices
            && Objects.equals(this.fieldSecurity, that.fieldSecurity)
            && Objects.equals(query, that.query);
    }

    @Override
    public int hashCode() {
        return Objects.hash(indices, privileges, allowRestrictedIndices, fieldSecurity, query);
    }

    @Override
    public String toString() {
        try {
            return XContentHelper.toXContent(this, XContentType.JSON, true).utf8ToString();
        } catch (IOException e) {
            throw new RuntimeException("Unexpected", e);
        }
    }

    @Override
    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
        builder.startObject();
        builder.field(NAMES.getPreferredName(), indices);
        builder.field(PRIVILEGES.getPreferredName(), privileges);
        builder.field(ALLOW_RESTRICTED_INDICES.getPreferredName(), allowRestrictedIndices);
        if (fieldSecurity != null) {
            builder.field(FIELD_PERMISSIONS.getPreferredName(), fieldSecurity, params);
        }
        if (isUsingDocumentLevelSecurity()) {
            builder.field("query", query);
        }
        return builder.endObject();
    }

    public static IndicesPrivileges fromXContent(XContentParser parser) {
        return PARSER.apply(parser, null);
    }

    public static Builder builder() {
        return new Builder();
    }

    public static final class Builder {

        private @Nullable Collection indices = null;
        private @Nullable Collection privileges = null;
        private @Nullable Collection grantedFields = null;
        private @Nullable Collection deniedFields = null;
        private @Nullable String query = null;
        boolean allowRestrictedIndices = false;

        public Builder() {}

        public Builder indices(String... indices) {
            return indices(Arrays.asList(Objects.requireNonNull(indices, "indices required")));
        }

        public Builder indices(Collection indices) {
            this.indices = Objects.requireNonNull(indices, "indices required");
            return this;
        }

        public Builder privileges(String... privileges) {
            return privileges(Arrays.asList(Objects.requireNonNull(privileges, "privileges required")));
        }

        public Builder privileges(Collection privileges) {
            this.privileges = Objects.requireNonNull(privileges, "privileges required");
            return this;
        }

        public Builder grantedFields(@Nullable String... grantedFields) {
            if (grantedFields == null) {
                this.grantedFields = null;
                return this;
            }
            return grantedFields(Arrays.asList(grantedFields));
        }

        public Builder grantedFields(@Nullable Collection grantedFields) {
            this.grantedFields = grantedFields;
            return this;
        }

        public Builder deniedFields(@Nullable String... deniedFields) {
            if (deniedFields == null) {
                this.deniedFields = null;
                return this;
            }
            return deniedFields(Arrays.asList(deniedFields));
        }

        public Builder deniedFields(@Nullable Collection deniedFields) {
            this.deniedFields = deniedFields;
            return this;
        }

        public Builder query(@Nullable String query) {
            this.query = query;
            return this;
        }

        public Builder allowRestrictedIndices(boolean allow) {
            this.allowRestrictedIndices = allow;
            return this;
        }

        public IndicesPrivileges build() {
            final FieldSecurity fieldSecurity;
            if (grantedFields == null && deniedFields == null) {
                fieldSecurity = null;
            } else {
                fieldSecurity = new FieldSecurity(grantedFields, deniedFields);
            }
            return new IndicesPrivileges(indices, privileges, allowRestrictedIndices, fieldSecurity, query);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy