Exemplo n.º 1
0
        async Task <(bool isAuthenticated, bool serviceIdentityFound)> AuthenticateWithAuthChain(T credentials, string actorDeviceId, bool syncServiceIdentity)
        {
            // The auth target is the first element of the authchain
            Option <string> authTargetOption = AuthChainHelpers.GetAuthTarget(credentials.AuthChain);
            string          authTarget       = authTargetOption.Expect(() => new InvalidOperationException("Credentials should always have a valid auth-chain for OnBehalfOf authentication"));

            // For nested Edge, we need to check that we have
            // a valid authchain for the target identity
            Option <string> authChain = await this.deviceScopeIdentitiesCache.GetAuthChain(authTarget);

            if (!authChain.HasValue)
            {
                Events.NoAuthChain(authTarget);
                return(false, false);
            }

            // Check that the actor is authorized to connect OnBehalfOf of the target
            if (!AuthChainHelpers.ValidateAuthChain(actorDeviceId, authTarget, authChain.OrDefault()))
            {
                // We found the target identity in our cache, but can't proceed with auth
                Events.UnauthorizedAuthChain(actorDeviceId, authTarget, authChain.OrDefault());
                return(false, true);
            }

            // Check credentials against the acting EdgeHub
            string actorEdgeHubId = actorDeviceId + $"/{Constants.EdgeHubModuleId}";

            return(await this.AuthenticateWithServiceIdentity(credentials, actorEdgeHubId, syncServiceIdentity));
        }
Exemplo n.º 2
0
        async Task <(bool isAuthenticated, bool serviceIdentityFound)> AuthenticateWithAuthChain(T credentials, string actorDeviceId, bool syncServiceIdentity)
        {
            // The auth target is the first element of the authchain
            Option <string> authTargetOption = AuthChainHelpers.GetAuthTarget(credentials.AuthChain);
            string          authTarget       = authTargetOption.Expect(() => new InvalidOperationException("Credentials should always have a valid auth-chain for OnBehalfOf authentication"));

            // For nested Edge, we need to check that we have
            // a valid authchain for the target identity
            Option <string> authChain = await this.deviceScopeIdentitiesCache.GetAuthChain(authTarget);

            if (!authChain.HasValue)
            {
                // The auth-target might be a new device that was recently added, and our
                // cache might not have it yet. Try refreshing the target identity to see
                // if we can get it from upstream.
                Events.NoAuthChainResyncing(authTarget, actorDeviceId);
                await this.deviceScopeIdentitiesCache.RefreshServiceIdentityOnBehalfOf(authTarget, actorDeviceId);

                authChain = await this.deviceScopeIdentitiesCache.GetAuthChain(authTarget);

                if (!authChain.HasValue)
                {
                    // Still don't have a valid auth-chain for the target, it must be
                    // out of scope, so we're done here
                    Events.NoAuthChain(authTarget);
                    return(false, false);
                }
            }

            // Check that the actor is authorized to connect OnBehalfOf of the target
            if (!AuthChainHelpers.ValidateAuthChain(actorDeviceId, authTarget, authChain.OrDefault()))
            {
                // We found the target identity in our cache, but can't proceed with auth
                Events.UnauthorizedAuthChain(actorDeviceId, authTarget, authChain.OrDefault());
                return(false, true);
            }

            // Check credentials against the acting EdgeHub, since we would have
            // already refreshed the target identity on failure, there's no need
            // to have AuthenticateWithServiceIdentity do it again.
            string actorEdgeHubId = actorDeviceId + $"/{Constants.EdgeHubModuleId}";

            return(await this.AuthenticateWithServiceIdentity(credentials, actorEdgeHubId, false));
        }
        public async Task Add(IClientCredentials clientCredentials)
        {
            if (clientCredentials is ITokenCredentials tokenCredentials)
            {
                string targetId = AuthChainHelpers.GetAuthTarget(tokenCredentials.AuthChain).GetOrElse(tokenCredentials.Identity.Id);

                try
                {
                    var    tokenCredentialsData   = new TokenCredentialsData(tokenCredentials.Token, tokenCredentials.IsUpdatable, tokenCredentials.AuthChain);
                    string tokenCredentialsString = JsonConvert.SerializeObject(tokenCredentialsData);
                    await this.encryptedStore.Put(targetId, tokenCredentialsString);

                    Events.Stored(clientCredentials.Identity.Id);
                }
                catch (Exception e)
                {
                    Events.ErrorStoring(e, clientCredentials.Identity.Id);
                }
            }
        }
Exemplo n.º 4
0
        void UpdateCachedCredentials(IClientCredentials clientCredentials)
        {
            string targetId = AuthChainHelpers.GetAuthTarget(clientCredentials.AuthChain).GetOrElse(clientCredentials.Identity.Id);

            if (clientCredentials.AuthChain.HasValue)
            {
                // OnBehalfOf connection from a child Edge, there should always be an actor device
                string actorDeviceId = AuthChainHelpers.GetActorDeviceId(clientCredentials.AuthChain)
                                       .Expect(() => new ArgumentException($"Invalid auth-chain: {clientCredentials.AuthChain.OrDefault()}"));

                // Only EdgeHub can act OnBehalfOf another identity
                string actorId = $"{actorDeviceId}/{Constants.EdgeHubModuleId}";

                if (!this.onBehalfOfRelations.ContainsKey(actorId))
                {
                    // Create a new OnBehalfOf mapping for this actor Edge
                    this.onBehalfOfRelations[actorId] = new HashSet <string>();
                }

                // Update our books for the new relation
                this.onBehalfOfRelations[actorId].Add(targetId);
            }
            else
            {
                // If there's no auth-chain, then this could be a credential update
                // for a child EdgeHub acting OnBehalfOf other identities
                if (this.onBehalfOfRelations.TryGetValue(clientCredentials.Identity.Id, out HashSet <string> onBehalfOfClients))
                {
                    // Need to update all clients that the child EdgeHub is acting OnBehalfOf
                    foreach (string client in onBehalfOfClients)
                    {
                        IClientCredentials updatedCredentials = GetCredentialsWithOnBehalfOfUpdates(this.credentials[client], clientCredentials);
                        this.credentials[client] = updatedCredentials;
                    }
                }
            }

            // Update the client credentials
            this.credentials[targetId] = clientCredentials;
        }