Beispiel #1
0
        async Task <IImmutableDictionary <string, IModuleIdentity> > GetModuleIdentitiesAsync(Diff diff)
        {
            // System modules have different module names and identity names. We need to convert module names to module identity names
            // and vice versa, to make sure the right values are being used.
            // TODO - This will fail if the user adds modules with the same module name as a system module - for example a module called
            // edgeHub. We might have to catch such cases and flag them as error (or handle them in some other way).
            IEnumerable <string> updatedModuleIdentites = diff.AddedOrUpdated.Select(m => ModuleIdentityHelper.GetModuleIdentityName(m.Name));
            IEnumerable <string> removedModuleIdentites = diff.Removed.Select(m => ModuleIdentityHelper.GetModuleIdentityName(m));

            List <Module> modules = (await this.serviceClient.GetModules()).ToList();

            ImmutableDictionary <string, Module> modulesDict = modules.ToImmutableDictionary(p => p.Id);

            IEnumerable <string> createIdentities = updatedModuleIdentites.Where(m => !modulesDict.ContainsKey(m));
            IEnumerable <string> removeIdentities = removedModuleIdentites.Where(
                m => modulesDict.ContainsKey(m) &&
                string.Equals(modulesDict.GetValueOrDefault(m).ManagedBy, Constants.ModuleIdentityEdgeManagedByValue, StringComparison.OrdinalIgnoreCase));

            // Update any identities that don't have SAS auth type or where the keys are null (this will happen for single device deployments,
            // where the identities of modules are created, but the auth keys are not set).
            IEnumerable <Module> updateIdentities = modules.Where(
                m => m.Authentication == null ||
                m.Authentication.Type != AuthenticationType.Sas ||
                m.Authentication.SymmetricKey == null ||
                (m.Authentication.SymmetricKey.PrimaryKey == null && m.Authentication.SymmetricKey.SecondaryKey == null))
                                                    .Select(
                m =>
            {
                m.Authentication = new AuthenticationMechanism
                {
                    Type = AuthenticationType.Sas
                };
                return(m);
            }).ToList();

            List <Module> updatedModulesIndentity            = (await this.UpdateServiceModulesIdentityAsync(removeIdentities, createIdentities, updateIdentities)).ToList();
            ImmutableDictionary <string, Module> updatedDict = updatedModulesIndentity.ToImmutableDictionary(p => p.Id);

            IEnumerable <IModuleIdentity> moduleIdentities;

            moduleIdentities = updatedModulesIndentity.Concat(modules.Where(p => !updatedDict.ContainsKey(p.Id))).Select(
                p =>
            {
                string connectionString = this.GetModuleConnectionString(p);
                return(new ModuleIdentity(
                           this.iothubHostName,
                           this.deviceId,
                           p.Id,
                           new ConnectionStringCredentials(connectionString)));
            });

            return(moduleIdentities.ToImmutableDictionary(m => ModuleIdentityHelper.GetModuleName(m.ModuleId)));
        }
        public async Task <IImmutableDictionary <string, IModuleIdentity> > GetModuleIdentitiesAsync(ModuleSet desired, ModuleSet current)
        {
            Diff diff = desired.Diff(current);

            if (diff.IsEmpty)
            {
                return(ImmutableDictionary <string, IModuleIdentity> .Empty);
            }

            IList <string>       updatedModuleNames = diff.Updated.Select(m => ModuleIdentityHelper.GetModuleIdentityName(m.Name)).ToList();
            IEnumerable <string> removedModuleNames = diff.Removed.Select(m => ModuleIdentityHelper.GetModuleIdentityName(m));

            IImmutableDictionary <string, Identity> identities = (await this.identityManager.GetIdentities()).ToImmutableDictionary(i => i.ModuleId);

            // Create identities for all modules that are in the deployment but aren't in iotedged.
            IEnumerable <string> createIdentities = updatedModuleNames.Where(m => !identities.ContainsKey(m));

            // Update identities for all modules that are in the deployment and are in iotedged (except for Edge Agent which gets special
            // treatment in iotedged).
            //
            // NOTE: This update can potentiatlly be made more efficient by checking that an update is actually needed, i.e. if auth type
            // is not SAS and/or if the credentials are not what iotedged expects it to be.
            IEnumerable <Identity> updateIdentities = updatedModuleNames
                                                      .Where(m => identities.ContainsKey(m) && m != Constants.EdgeAgentModuleIdentityName)
                                                      .Select(m => identities[m]);

            // Remove identities which exist in iotedged but don't exist in the deployment anymore. We exclude however, identities that
            // aren't managed by Edge since these have been created by some out-of-band process and Edge doesn't "own" the identity.
            IEnumerable <string> removeIdentities = removedModuleNames.Where(m => identities.ContainsKey(m) &&
                                                                             Constants.ModuleIdentityEdgeManagedByValue.Equals(identities[m].ManagedBy, StringComparison.OrdinalIgnoreCase));

            // First remove identities (so that we don't go over the IoTHub limit).
            await Task.WhenAll(removeIdentities.Select(i => this.identityManager.DeleteIdentityAsync(i)));

            // Create/update identities.
            IEnumerable <Task <Identity> > createTasks = createIdentities.Select(i => this.identityManager.CreateIdentityAsync(i, Constants.ModuleIdentityEdgeManagedByValue));
            IEnumerable <Task <Identity> > updateTasks = updateIdentities.Select(i => this.identityManager.UpdateIdentityAsync(i.ModuleId, i.GenerationId, i.ManagedBy));

            Identity[] upsertedIdentities = await Task.WhenAll(createTasks.Concat(updateTasks));

            List <IModuleIdentity> moduleIdentities = upsertedIdentities.Select(m => this.GetModuleIdentity(m)).ToList();

            // Add the module identity for Edge Agent in the returned dictionary
            // because is was excluded from the update call.
            if (identities.ContainsKey(Constants.EdgeAgentModuleIdentityName))
            {
                moduleIdentities.Add(this.GetModuleIdentity(identities[Constants.EdgeAgentModuleIdentityName]));
            }
            return(moduleIdentities.ToImmutableDictionary(m => ModuleIdentityHelper.GetModuleName(m.ModuleId)));
        }