private async Task <List <Rule> > ProcessPolicyFile(string policyPath, string org, string app, RequestToDelete deleteRequest) { List <Rule> currentRules = new List <Rule>(); string leaseId = await _policyRepository.TryAcquireBlobLease(policyPath); if (leaseId == null) { _logger.LogError("Could not acquire blob lease lock on delegation policy at path: {policyPath}", policyPath); return(null); } try { bool isAllRulesDeleted = false; string coveredBy = DelegationHelper.GetCoveredByFromMatch(deleteRequest.PolicyMatch.CoveredBy, out int?coveredByUserId, out int?coveredByPartyId); string offeredBy = deleteRequest.PolicyMatch.OfferedByPartyId.ToString(); DelegationChange currentChange = await _delegationRepository.GetCurrentDelegationChange($"{org}/{app}", deleteRequest.PolicyMatch.OfferedByPartyId, coveredByPartyId, coveredByUserId); XacmlPolicy existingDelegationPolicy = null; if (currentChange.DelegationChangeType == DelegationChangeType.RevokeLast) { _logger.LogWarning("The policy is already deleted for App: {org}/{app} CoveredBy: {coveredBy} OfferedBy: {offeredBy}", org, app, coveredBy, offeredBy); return(null); } existingDelegationPolicy = await _prp.GetPolicyVersionAsync(currentChange.BlobStoragePolicyPath, currentChange.BlobStorageVersionId); foreach (string ruleId in deleteRequest.RuleIds) { XacmlRule xacmlRuleToRemove = existingDelegationPolicy.Rules.FirstOrDefault(r => r.RuleId == ruleId); if (xacmlRuleToRemove == null) { _logger.LogWarning("The rule with id: {ruleId} does not exist in policy with path: {policyPath}", ruleId, policyPath); continue; } existingDelegationPolicy.Rules.Remove(xacmlRuleToRemove); Rule currentRule = PolicyHelper.CreateRuleFromPolicyAndRuleMatch(deleteRequest, xacmlRuleToRemove); currentRules.Add(currentRule); } isAllRulesDeleted = existingDelegationPolicy.Rules.Count == 0; // if nothing is deleted no update has been done and policy and postgree update can be skipped if (currentRules.Count > 0) { Response <BlobContentInfo> response; try { // Write delegation policy to blob storage MemoryStream dataStream = PolicyHelper.GetXmlMemoryStreamFromXacmlPolicy(existingDelegationPolicy); response = await _policyRepository.WritePolicyConditionallyAsync(policyPath, dataStream, leaseId); } catch (Exception ex) { _logger.LogError(ex, "Writing of delegation policy at path: {policyPath} failed. Is delegation blob storage account alive and well?", policyPath); return(null); } // Write delegation change to postgresql DelegationChange change = new DelegationChange { DelegationChangeType = isAllRulesDeleted ? DelegationChangeType.RevokeLast : DelegationChangeType.Revoke, AltinnAppId = $"{org}/{app}", OfferedByPartyId = deleteRequest.PolicyMatch.OfferedByPartyId, CoveredByPartyId = coveredByPartyId, CoveredByUserId = coveredByUserId, PerformedByUserId = deleteRequest.DeletedByUserId, BlobStoragePolicyPath = policyPath, BlobStorageVersionId = response.Value.VersionId }; change = await _delegationRepository.InsertDelegation(change); if (change == null || change.DelegationChangeId <= 0) { // Comment: // This means that the current version of the root blob is no longer in sync with changes in authorization postgresql delegation.delegatedpolicy table. // The root blob is in effect orphaned/ignored as the delegation policies are always to be read by version, and will be overritten by the next delegation change. _logger.LogError("Writing of delegation change to authorization postgresql database failed for changes to delegation policy at path: {policyPath}. is authorization postgresql database alive and well?", policyPath); return(null); } try { await _eventQueue.Push(change); } catch (Exception ex) { _logger.LogCritical(new EventId(delegationChangeEventQueueErrorId, "DelegationChangeEventQueue.Push.Error"), ex, "DeleteRules could not push DelegationChangeEvent to DelegationChangeEventQueue. DelegationChangeEvent must be retried for successful sync with SBL Authorization. DelegationChange: {change}", change); } } } catch (Exception ex) { _logger.LogError(ex, "An exception occured while processing rules to delete in policy: {policyPath}", policyPath); return(null); } finally { _policyRepository.ReleaseBlobLease(policyPath, leaseId); } return(currentRules); }
private async Task <List <Rule> > DeleteAllRulesInPolicy(RequestToDelete policyToDelete) { DelegationHelper.TryGetResourceFromAttributeMatch(policyToDelete.PolicyMatch.Resource, out string org, out string app); string coveredBy = DelegationHelper.GetCoveredByFromMatch(policyToDelete.PolicyMatch.CoveredBy, out int?coveredByUserId, out int?coveredByPartyId); string policyPath; try { policyPath = PolicyHelper.GetAltinnAppDelegationPolicyPath(org, app, policyToDelete.PolicyMatch.OfferedByPartyId.ToString(), coveredByUserId, coveredByPartyId); } catch (Exception ex) { _logger.LogError(ex, "Not possible to build policy path App: {org}/{app} CoveredBy: {coveredBy} OfferedBy: {policyToDelete.PolicyMatch.OfferedByPartyId}", org, app, coveredBy, policyToDelete.PolicyMatch.OfferedByPartyId); return(null); } if (!await _policyRepository.PolicyExistsAsync(policyPath)) { _logger.LogWarning("No blob was found for the expected path: {policyPath} this must be removed without upading the database", policyPath); return(null); } string leaseId = await _policyRepository.TryAcquireBlobLease(policyPath); if (leaseId == null) { _logger.LogError("Could not acquire blob lease on delegation policy at path: {policyPath}", policyPath); return(null); } try { DelegationChange currentChange = await _delegationRepository.GetCurrentDelegationChange($"{org}/{app}", policyToDelete.PolicyMatch.OfferedByPartyId, coveredByPartyId, coveredByUserId); if (currentChange.DelegationChangeType == DelegationChangeType.RevokeLast) { _logger.LogWarning("The policy is already deleted for App: {org}/{app} CoveredBy: {coveredBy} OfferedBy: {policyToDelete.PolicyMatch.OfferedByPartyId}", org, app, coveredBy, policyToDelete.PolicyMatch.OfferedByPartyId); return(null); } XacmlPolicy existingDelegationPolicy = await _prp.GetPolicyVersionAsync(currentChange.BlobStoragePolicyPath, currentChange.BlobStorageVersionId); List <Rule> currentPolicyRules = new List <Rule>(); foreach (XacmlRule xacmlRule in existingDelegationPolicy.Rules) { currentPolicyRules.Add(PolicyHelper.CreateRuleFromPolicyAndRuleMatch(policyToDelete, xacmlRule)); } existingDelegationPolicy.Rules.Clear(); Response <BlobContentInfo> response; try { MemoryStream dataStream = PolicyHelper.GetXmlMemoryStreamFromXacmlPolicy(existingDelegationPolicy); response = await _policyRepository.WritePolicyConditionallyAsync(policyPath, dataStream, leaseId); } catch (Exception ex) { _logger.LogError(ex, "Writing of delegation policy at path: {policyPath} failed. Is delegation blob storage account alive and well?}", policyPath); return(null); } DelegationChange change = new DelegationChange { DelegationChangeType = DelegationChangeType.RevokeLast, AltinnAppId = $"{org}/{app}", OfferedByPartyId = policyToDelete.PolicyMatch.OfferedByPartyId, CoveredByPartyId = coveredByPartyId, CoveredByUserId = coveredByUserId, PerformedByUserId = policyToDelete.DeletedByUserId, BlobStoragePolicyPath = policyPath, BlobStorageVersionId = response.Value.VersionId }; change = await _delegationRepository.InsertDelegation(change); if (change == null || change.DelegationChangeId <= 0) { // Comment: // This means that the current version of the root blob is no longer in sync with changes in authorization postgresql delegation.delegatedpolicy table. // The root blob is in effect orphaned/ignored as the delegation policies are always to be read by version, and will be overritten by the next delegation change. _logger.LogError("Writing of delegation change to authorization postgresql database failed for changes to delegation policy at path: {policyPath}. is authorization postgresql database alive and well?", policyPath); return(null); } try { await _eventQueue.Push(change); } catch (Exception ex) { _logger.LogCritical(new EventId(delegationChangeEventQueueErrorId, "DelegationChangeEventQueue.Push.Error"), ex, "DeletePolicy could not push DelegationChangeEvent to DelegationChangeEventQueue. DelegationChangeEvent must be retried for successful sync with SBL Authorization. DelegationChange: {change}", change); } return(currentPolicyRules); } catch (Exception ex) { _logger.LogError(ex, "An exception occured while processing rules to delete in policy: {policyPath}", policyPath); return(null); } finally { _policyRepository.ReleaseBlobLease(policyPath, leaseId); } }
private async Task <bool> WriteDelegationPolicyInternal(string policyPath, List <Rule> rules) { if (!DelegationHelper.TryGetDelegationParamsFromRule(rules.First(), out string org, out string app, out int offeredByPartyId, out int?coveredByPartyId, out int?coveredByUserId, out int delegatedByUserId)) { _logger.LogWarning("This should not happen. Incomplete rule model received for delegation to delegation policy at: {policyPath}. Incomplete model should have been returned in unsortable rule set by TryWriteDelegationPolicyRules. DelegationHelper.SortRulesByDelegationPolicyPath might be broken.", policyPath); return(false); } XacmlPolicy appPolicy = await _prp.GetPolicyAsync(org, app); if (appPolicy == null) { _logger.LogWarning("No valid App policy found for delegation policy path: {policyPath}", policyPath); return(false); } foreach (Rule rule in rules) { if (!DelegationHelper.PolicyContainsMatchingRule(appPolicy, rule)) { _logger.LogWarning("Matching rule not found in app policy. Action might not exist for Resource, or Resource itself might not exist. Delegation policy path: {policyPath}. Rule: {rule}", policyPath, rule); return(false); } } if (!await _policyRepository.PolicyExistsAsync(policyPath)) { // Create a new empty blob for lease locking await _policyRepository.WritePolicyAsync(policyPath, new MemoryStream()); } string leaseId = await _policyRepository.TryAcquireBlobLease(policyPath); if (leaseId != null) { try { // Check for a current delegation change from postgresql DelegationChange currentChange = await _delegationRepository.GetCurrentDelegationChange($"{org}/{app}", offeredByPartyId, coveredByPartyId, coveredByUserId); XacmlPolicy existingDelegationPolicy = null; if (currentChange != null && currentChange.DelegationChangeType != DelegationChangeType.RevokeLast) { existingDelegationPolicy = await _prp.GetPolicyVersionAsync(policyPath, currentChange.BlobStorageVersionId); } // Build delegation XacmlPolicy either as a new policy or add rules to existing XacmlPolicy delegationPolicy; if (existingDelegationPolicy != null) { delegationPolicy = existingDelegationPolicy; foreach (Rule rule in rules) { if (!DelegationHelper.PolicyContainsMatchingRule(delegationPolicy, rule)) { delegationPolicy.Rules.Add(PolicyHelper.BuildDelegationRule(org, app, offeredByPartyId, coveredByPartyId, coveredByUserId, rule)); } } } else { delegationPolicy = PolicyHelper.BuildDelegationPolicy(org, app, offeredByPartyId, coveredByPartyId, coveredByUserId, rules); } // Write delegation policy to blob storage MemoryStream dataStream = PolicyHelper.GetXmlMemoryStreamFromXacmlPolicy(delegationPolicy); Response <BlobContentInfo> blobResponse = await _policyRepository.WritePolicyConditionallyAsync(policyPath, dataStream, leaseId); Response httpResponse = blobResponse.GetRawResponse(); if (httpResponse.Status != (int)HttpStatusCode.Created) { _logger.LogError("Writing of delegation policy at path: {policyPath} failed. Response Status Code:\n{httpResponse.Status}. Response Reason Phrase:\n{httpResponse.ReasonPhrase}", policyPath, httpResponse.Status, httpResponse.ReasonPhrase); return(false); } // Write delegation change to postgresql DelegationChange change = new DelegationChange { DelegationChangeType = DelegationChangeType.Grant, AltinnAppId = $"{org}/{app}", OfferedByPartyId = offeredByPartyId, CoveredByPartyId = coveredByPartyId, CoveredByUserId = coveredByUserId, PerformedByUserId = delegatedByUserId, BlobStoragePolicyPath = policyPath, BlobStorageVersionId = blobResponse.Value.VersionId }; change = await _delegationRepository.InsertDelegation(change); if (change == null || change.DelegationChangeId <= 0) { // Comment: // This means that the current version of the root blob is no longer in sync with changes in authorization postgresql delegation.delegatedpolicy table. // The root blob is in effect orphaned/ignored as the delegation policies are always to be read by version, and will be overritten by the next delegation change. _logger.LogError("Writing of delegation change to authorization postgresql database failed for changes to delegation policy at path: {policyPath}", policyPath); return(false); } try { await _eventQueue.Push(change); } catch (Exception ex) { _logger.LogCritical(new EventId(delegationChangeEventQueueErrorId, "DelegationChangeEventQueue.Push.Error"), ex, "AddRules could not push DelegationChangeEvent to DelegationChangeEventQueue. DelegationChangeEvent must be retried for successful sync with SBL Authorization. DelegationChange: {change}", change); } return(true); } finally { _policyRepository.ReleaseBlobLease(policyPath, leaseId); } } _logger.LogInformation("Could not acquire blob lease lock on delegation policy at path: {policyPath}", policyPath); return(false); }