Help us shape the future of Go! Take the 2026 Go Developer Survey

edgraph

package
v25.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 13, 2026 License: Apache-2.0 Imports: 49 Imported by: 2

Documentation

Index

Constants

View Source
const PresharedIssuer = "dgraph-security-token"

PresharedIssuer identifies the --security auth token as the thing that vouched for a Principal.

View Source
const PresharedSubject = "PoorManAuth"

PresharedSubject is the Principal.Subject a caller authenticated by the --security auth token carries.

The value matches audit.PoorManAuth deliberately. Audit prefers the resolved Principal over re-parsing the credential, so minting a Principal for a token-bearing caller would otherwise change what every such request logs. Pinned by TestPresharedSubjectMatchesAudit.

Variables

This section is empty.

Functions

func AuthorizeCapability added in v25.5.0

func AuthorizeCapability(ctx context.Context, c Capability) error

AuthorizeCapability authorizes c for the caller on ctx under the installed policy. This is the entry point every call site uses; the interface exists so what it resolves to can be replaced.

NOTE: do not wrap the returned error. Prepend to the message if needed, and propagate the gRPC code.

func EnforceAnonymousPosture added in v25.5.0

func EnforceAnonymousPosture(posture x.AnonymousPosture)

EnforceAnonymousPosture installs the --security "anonymous=..." floor over whatever policy is currently installed. AnonymousFull installs nothing, so a cluster running the shipped default carries no extra indirection at all.

Call it during command setup, after any deployment-specific SetAccessController and before any listener starts serving: it captures the policy installed at the moment it runs, so installing one afterwards would silently discard the floor.

func GetGQLSchema

func GetGQLSchema(namespace uint64) (uid, graphQLSchema string, err error)

GetGQLSchema queries for the GraphQL schema node, and returns the uid and the GraphQL schema. If multiple schema nodes were found, it returns an error.

func Init

func Init()

func InitializeAcl

func InitializeAcl(closer *z.Closer)

upserts the Groot account.

func InsertDropRecord

func InsertDropRecord(ctx context.Context, dropOp string) error

InsertDropRecord is used to insert a helper record when a DROP operation is performed. This helper record lets us know during backup that a DROP operation was performed and that we need to write this information in backup manifest. So that while restoring from a backup series, we can create an exact replica of the system which existed at the time the last backup was taken. Note that if the server crashes after the DROP operation & before this helper record is inserted, then restoring from the incremental backup of such a DB would restore even the dropped data back. This is also used to capture the delete namespace operation during backup.

func ParseMutationObject

func ParseMutationObject(ctx context.Context, mu *api.Mutation) (*dql.Mutation, error)

ParseMutationObject tries to consolidate fields of the api.Mutation into the corresponding field of the returned dql.Mutation. For example, the 3 fields, api.Mutation#SetJson, api.Mutation#SetNquads and api.Mutation#Set are consolidated into the dql.Mutation.Set field. Similarly the 3 fields api.Mutation#DeleteJson, api.Mutation#DelNquads and api.Mutation#Del are merged into the dql.Mutation#Del field.

func PresharedAuthenticator added in v25.5.0

func PresharedAuthenticator() x.Authenticator

PresharedAuthenticator returns the built-in authenticator: Dgraph's own ACL access JWT first, then the --security auth token.

The token half is what makes a closed --security "anonymous=..." posture usable without standing up full ACL. Before this, the token was a boolean check -- hasPoormansAuth answered "may this request proceed" and produced no identity -- so a token-bearing caller was indistinguishable from an anonymous one, and a posture keyed on "did this caller present a credential" would have denied it.

Ordering is ACL first because ACL identifies a user while the token identifies a client service, and the more specific identity should win when a request carries both. It also costs nothing when ACL is off: aclAuthenticator returns (nil, nil) immediately in that configuration.

func ProcessPersistedQuery

func ProcessPersistedQuery(ctx context.Context, gqlReq *schema.Request) error

ProcessPersistedQuery stores and retrieves persisted queries by following waterfall logic:

  1. If sha256Hash is not provided process queries without persisting
  2. If sha256Hash is provided try retrieving persisted queries 2a. Persisted Query not found i) If query is not provided then throw "PersistedQueryNotFound" ii) If query is provided then store query in dgraph only if sha256 of the query is correct otherwise throw "provided sha does not match query" 2b. Persisted Query found i) If query is not provided then update gqlRes with the found query and proceed ii) If query is provided then match query retrieved, if identical do nothing else throw "query does not match persisted query"

func RefreshACLs

func RefreshACLs(ctx context.Context)

func RegisterCapabilitySource added in v25.5.0

func RegisterCapabilitySource(s CapabilitySource)

RegisterCapabilitySource appends a source, consulted after the ones already registered. Call it during command setup, before any listener starts serving; it is not safe to call concurrently with request handling.

func RequireIdentifiedAdmin added in v25.5.0

func RequireIdentifiedAdmin(ctx context.Context, op string) error

RequireIdentifiedAdmin rejects an anonymous caller of an administrative operation that is not a Capability check, under --security "anonymous=data" and "anonymous=none".

Alter is the case that needs it. Only drop_all reaches a Capability, so before this an anonymous caller under a closed posture could still change the schema, drop a predicate, or drop_op DATA -- which empties the namespace -- because the remaining gates are the whitelist and token check (hasAdminAuth) and ACL (authorizeAlter), and neither consults the Principal. With an open whitelist and nothing else configured, that left one-request data destruction reachable under exactly the posture meant to close it.

It treats every Alter as administrative, schema changes included. Dgraph already does: /alter is gated by hasAdminAuth, whose error reads "Token needed for Admin operations". A posture that admitted schema changes but refused drops would be a line operators had to learn, and drop_op DATA is what getting it wrong costs.

func RequireIdentifiedCaller added in v25.5.0

func RequireIdentifiedCaller(ctx context.Context, op string) error

RequireIdentifiedCaller rejects an anonymous caller's ordinary data access under --security "anonymous=none".

Separate from AuthorizeCapability because queries, mutations, and commits are not capabilities and should not become them: a capability is cluster or tenant authority, deliberately coarse and deliberately few, while data access is decided per predicate. This is the one question the posture asks that predicate authorization cannot, because an anonymous caller on an ACL-off cluster has blanket predicate access by construction.

It is a no-op under anonymous=full and anonymous=data, which is why the call sites can be unconditional.

func SetAccessController added in v25.5.0

func SetAccessController(ac AccessController)

SetAccessController installs a deployment-specific policy, replacing the built-in one that authorizes against Dgraph's own ACL. Call it during command setup, before any listener starts serving. Passing nil restores the built-in.

func SubscribeForAclUpdates

func SubscribeForAclUpdates(closer *z.Closer)

SubscribeForAclUpdates subscribes for ACL predicates and updates the acl cache.

func UpdateGQLSchema

func UpdateGQLSchema(ctx context.Context, gqlSchema,
	dgraphSchema string) (*pb.UpdateGraphQLSchemaResponse, error)

UpdateGQLSchema updates the GraphQL and Dgraph schemas using the given inputs. It first validates and parses the dgraphSchema given in input. If that fails, it returns an error. All this is done on the alpha on which the update request is received. Then it sends an update request to the worker, which is executed only on Group-1 leader.

Types

type AccessController added in v25.5.0

type AccessController interface {
	// Name identifies the policy, for logs and for the error an unimplemented
	// capability produces.
	Name() string

	// AuthorizeCapability reports whether the caller on ctx holds c, returning a
	// gRPC status error when it does not.
	//
	// Callers must not wrap the returned error. They may prepend context to its
	// message, but the code has to survive — several endpoints distinguish
	// Unauthenticated from PermissionDenied, and clients act on that difference.
	AuthorizeCapability(ctx context.Context, c Capability) error

	// AuthorizePredicates partitions preds into what the caller may and may not
	// access under op.
	//
	// It deliberately does not return "denied". A query names predicates the caller
	// may have no business seeing, and the established behavior is to drop them and
	// answer the rest rather than refuse the whole request — so the result is data
	// the caller acts on, not a verdict. See PredResult.
	//
	// The error is for a policy that could not reach an answer at all: the built-in
	// one reads a local cache and never fails, but a policy that has to query the
	// graph can. An error must not be read as a denial.
	//
	// Identity comes from ctx, not from a parameter. Handing a policy Dgraph's own
	// userData would make every implementation speak ACL.
	AuthorizePredicates(ctx context.Context, preds []string, op *acl.Operation) (*PredResult, error)
}

AccessController decides what a verified caller may do.

It answers only authorization. Who the caller is has already been established by the time a method here runs — x.PrincipalFrom carries the answer — and which tenant the request operates in is the TenantResolver's business. Keeping all three apart is the point of the surrounding work; an implementation that verifies a credential or derives a namespace has taken on someone else's job.

Two methods rather than one, because the two questions have different shapes. A capability is a yes or no. Predicate access is a partition: the answer is which of the requested predicates are usable, and the caller proceeds with those.

type AuthMode

type AuthMode int
const (
	// NeedAuthorize is used to indicate that the request needs to be authorized.
	NeedAuthorize AuthMode = iota
	// NoAuthorize is used to indicate that authorization needs to be skipped.
	// Used when ACL needs to query information for performing the authorization check.
	NoAuthorize
)

type Capability added in v25.5.0

type Capability int

Capability is an authority over the cluster or a tenant, as opposed to access to particular predicates. Capabilities answer "may this caller perform this class of operation at all", and they are deliberately few: an operation that needs a finer distinction should be authorized on its predicates instead.

const (
	// CapClusterAdmin is authority over the whole cluster: creating and dropping
	// namespaces, dropping all data, resetting passwords across tenants. Nothing
	// scoped to a single tenant should require it.
	CapClusterAdmin Capability = iota

	// CapTenantAdmin is administrative authority within a tenant — reading cluster
	// state and health, arming an external-snapshot import.
	//
	// It is a weaker capability than CapClusterAdmin, and under the built-in policy
	// the difference is real but narrow: CapClusterAdmin additionally requires the
	// caller to be in the root namespace.
	CapTenantAdmin

	// CapAssumeTenant is the authority to act in a namespace other than the
	// caller's own. The live loader needs it for a galaxy-wide write.
	//
	// Split out from CapClusterAdmin even though the built-in policy resolves both
	// identically, because they are different powers and conflating them costs
	// something later: a scoped service account should be able to write across
	// tenants without also being able to drop the cluster.
	CapAssumeTenant

	// CapLeaseUIDs is the authority to lease a block of UIDs from Zero.
	//
	// Separate from CapClusterAdmin, which it briefly shared, because the callers
	// are not administrators: `dgraph live` allocates UIDs through this RPC on every
	// run — xidmap falls back to it whenever it was built without a direct Zero
	// connection — so folding it in made the loader require a whitelisted IP or an
	// auth token against any cluster running without ACL, where it had needed
	// neither.
	//
	// Tightening it is the same change as fail-closed galaxy-operation, with the same
	// cost and the same answer: it wants a flag-gated release rather than to ride
	// along. Under ACL it is guardian-of-the-root-namespace, exactly as it was before
	// capabilities existed.
	CapLeaseUIDs
)

func (Capability) String added in v25.5.0

func (c Capability) String() string

type CapabilitySource added in v25.5.0

type CapabilitySource interface {
	// Name identifies the source in logs and in the denial message, so an
	// operator can see which routes were tried.
	Name() string
	// Grants reports whether the caller holds c by this route. p is the verified
	// principal, or nil when the request carried no credential — a source keyed on
	// operator-level controls rather than identity still works in that case.
	Grants(ctx context.Context, p *x.Principal, c Capability) bool
}

CapabilitySource is one way a caller can come to hold a capability.

The built-in policy consults its sources in order and the first grant wins, so a deployment can add a path to cluster authority without replacing the whole policy. That matters because the alternative — SetAccessController — means reimplementing Dgraph's ACL rules in order to add one grant beside them.

A source answers only "does this caller hold c". It must not deny: returning false means "not by this route", and the next source still gets asked.

type GraphqlContextKey

type GraphqlContextKey int
const (
	// IsGraphql is used to validate requests which are allowed to mutate GraphQL reserved
	// predicates, like dgraph.graphql.schema and dgraph.graphql.xid.
	IsGraphql GraphqlContextKey = iota
	// Authorize is used to set if the request requires validation.
	Authorize
)

type PredResult added in v25.5.0

type PredResult struct {
	// Allowed lists the predicates the caller may access — but a nil Allowed means
	// *all* of them, not none.
	//
	// The sentinel is load-bearing and it predates this interface: a caller with
	// blanket access has no enumerable predicate list, and materializing one would
	// mean listing every predicate in the namespace on every request. Blocked is
	// still honored when Allowed is nil, which is how ACL predicates stay
	// unreadable even to a caller that may read everything else.
	Allowed []string

	// Blocked is the subset of the requested predicates the caller may not access.
	// Empty means none were refused.
	Blocked map[string]struct{}
}

PredResult is how a policy partitions the predicates a request named.

func AuthorizePredicates added in v25.5.0

func AuthorizePredicates(ctx context.Context, preds []string, op *acl.Operation) (*PredResult, error)

AuthorizePredicates partitions preds for the caller on ctx under the installed policy. See AccessController.AuthorizePredicates: an error means the policy could not decide, which is not the same as a denial.

type Request

type Request struct {
	// contains filtered or unexported fields
}

Request represents a query request sent to the doQuery() method on the Server. It contains all the metadata required to execute a query.

type ResetPasswordInput

type ResetPasswordInput struct {
	UserID    string
	Password  string
	Namespace uint64
}

type Server

type Server struct {
	// embedding the api.UnimplementedZeroServer struct to ensure forward compatibility of the server.
	api.UnimplementedDgraphServer
}

Server implements protos.DgraphServer

func (*Server) AllocateIDs

func (s *Server) AllocateIDs(ctx context.Context, req *api.AllocateIDsRequest) (
	*api.AllocateIDsResponse, error)

func (*Server) Alter

func (s *Server) Alter(ctx context.Context, op *api.Operation) (*api.Payload, error)

Alter handles requests to change the schema or remove parts or all of the data. It enforces the admin-IP-whitelist and ACL authorization checks.

func (*Server) AlterNoAuth added in v25.3.6

func (s *Server) AlterNoAuth(ctx context.Context, op *api.Operation) (*api.Payload, error)

AlterNoAuth is Alter without the admin-IP-whitelist and ACL authorization checks. It mirrors QueryNoAuth and is intended only for trusted in-process callers that run with a context.Background() and therefore carry no gRPC peer for x.HasWhitelistedIP to inspect — under the regular Alter path such calls are always rejected with "unable to find source ip", regardless of the --security whitelist setting. It must not be exposed to network clients.

It is restricted to schema operations: drop requests are refused so that bypassing auth can never be used to remove data.

func (*Server) CheckVersion

func (s *Server) CheckVersion(ctx context.Context, c *api.Check) (v *api.Version, err error)

CheckVersion returns the version of this Dgraph instance.

func (*Server) CommitOrAbort

func (s *Server) CommitOrAbort(ctx context.Context, tc *api.TxnContext) (*api.TxnContext, error)

CommitOrAbort commits or aborts a transaction.

func (*Server) CreateNamespace

func (*Server) CreateNamespaceInternal

func (s *Server) CreateNamespaceInternal(ctx context.Context, passwd string) (uint64, error)

CreateNamespaceInternal creates a new namespace. Only superadmin is authorized to do so. Authorization is handled by middlewares.

func (*Server) DeleteNamespace

func (s *Server) DeleteNamespace(ctx context.Context, namespace uint64) error

DeleteNamespace deletes a new namespace. Only superadmin is authorized to do so. Authorization is handled by middlewares.

func (*Server) DropNamespace

func (s *Server) DropNamespace(ctx context.Context, in *api.DropNamespaceRequest) (
	*api.DropNamespaceResponse, error)

func (*Server) Health

func (s *Server) Health(ctx context.Context, all bool) (*api.Response, error)

Health handles /health and /health?all requests.

func (*Server) ListNamespaces

func (*Server) Login

func (s *Server) Login(ctx context.Context,
	request *api.LoginRequest) (*api.Response, error)

Login handles login requests from clients.

func (*Server) Query

func (s *Server) Query(ctx context.Context, req *api.Request) (*api.Response, error)

func (*Server) QueryGraphQL

func (s *Server) QueryGraphQL(ctx context.Context, req *api.Request,
	field gqlSchema.Field) (*api.Response, error)

QueryGraphQL handles only GraphQL queries, neither mutations nor DQL.

func (*Server) QueryNoAuth

func (s *Server) QueryNoAuth(ctx context.Context, req *api.Request) (*api.Response, error)

func (*Server) QueryNoGrpc

func (s *Server) QueryNoGrpc(ctx context.Context, req *api.Request) (*api.Response, error)

Query handles queries or mutations

func (*Server) ResetPassword

func (s *Server) ResetPassword(ctx context.Context, inp *ResetPasswordInput) error

func (*Server) RunDQL

func (s *Server) RunDQL(ctx context.Context, req *api.RunDQLRequest) (*api.Response, error)

Alter handles requests to change the schema or remove parts or all of the data.

func (*Server) State

func (s *Server) State(ctx context.Context) (*api.Response, error)

State handles state requests

func (*Server) StreamExtSnapshot

func (s *Server) StreamExtSnapshot(stream api.Dgraph_StreamExtSnapshotServer) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL