/** * Copyright (c) Codice Foundation * <p/> * This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation, either version 3 of the * License, or any later version. * <p/> * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. A copy of the GNU Lesser General Public License * is distributed along with this program and can be found at * <http://www.gnu.org/licenses/lgpl.html>. **/ package org.codice.ddf.security.sts.claims.property; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.security.Principal; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import javax.security.auth.x500.X500Principal; import org.apache.commons.io.IOUtils; import org.apache.cxf.rt.security.claims.Claim; import org.apache.cxf.rt.security.claims.ClaimCollection; import org.apache.cxf.sts.claims.ClaimsHandler; import org.apache.cxf.sts.claims.ClaimsParameters; import org.apache.cxf.sts.claims.ProcessedClaim; import org.apache.cxf.sts.claims.ProcessedClaimCollection; import org.apache.cxf.sts.token.realm.RealmSupport; import org.boon.json.JsonFactory; import org.boon.json.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ddf.security.SubjectUtils; public class AttributeFileClaimsHandler implements ClaimsHandler, RealmSupport { private static final Logger LOGGER = LoggerFactory.getLogger(AttributeFileClaimsHandler.class); private static final ObjectMapper MAPPER = JsonFactory.create(); private String attributeFileLocation; private List<URI> supportedClaimTypes = new ArrayList<>(); private Map<String, Object> json; private List<String> supportedRealms; private String realm; public void init() { if (attributeFileLocation != null) { Path ddfHomePath = Paths.get(System.getProperty("ddf.home")); Path path = Paths.get(attributeFileLocation); if (!path.isAbsolute()) { path = Paths.get(ddfHomePath.toString(), path.toString()); } Set<String> claims = new HashSet<>(); try (InputStream stream = Files.newInputStream(path)) { String jsonString = IOUtils.toString(stream); json = MAPPER.parser().parseMap(jsonString); Set<Map.Entry<String, Object>> entries = json.entrySet(); for (Map.Entry<String, Object> entry : entries) { Object value = entry.getValue(); if (value instanceof Map) { Set keySet = ((Map) value).keySet(); for (Object key : keySet) { claims.add((String) key); } } } supportedClaimTypes.clear(); supportedClaimTypes.addAll(claims.stream() .map(URI::create) .collect(Collectors.toList())); } catch (IOException e) { LOGGER.info("Unable to read attribute file for system users. Set log level for \"org.codice.ddf.security.sts.claims.property\" to DEBUG for more information."); LOGGER.debug("Unable to read attribute file for system users.", e); } } } @Override public List<URI> getSupportedClaimTypes() { return supportedClaimTypes; } @Override public ProcessedClaimCollection retrieveClaimValues(ClaimCollection claimCollection, ClaimsParameters claimsParameters) { ProcessedClaimCollection claimsColl = new ProcessedClaimCollection(); Principal principal = claimsParameters.getPrincipal(); if (principal == null) { return claimsColl; } String name; if (principal instanceof X500Principal) { name = SubjectUtils.getCommonName((X500Principal) principal); } else { name = principal.getName(); } Object user = json.get(name); Map userMap = null; if (user != null) { if (user instanceof Map) { userMap = (Map) user; } } else { Set<Map.Entry<String, Object>> entries = json.entrySet(); for (Map.Entry<String, Object> entry : entries) { String key = entry.getKey(); Pattern pattern = Pattern.compile(key); Matcher matcher = pattern.matcher(principal.getName()); if (matcher.matches()) { userMap = (Map) entry.getValue(); break; } } } if (userMap == null) { return claimsColl; } for (Claim claim : claimCollection) { Object attributeValue = userMap.get(claim.getClaimType() .toString()); ProcessedClaim c = new ProcessedClaim(); c.setClaimType(claim.getClaimType()); c.setPrincipal(principal); if (attributeValue instanceof List) { ((List) attributeValue).forEach(c::addValue); claimsColl.add(c); } else if (attributeValue instanceof String) { c.addValue(attributeValue); claimsColl.add(c); } } return claimsColl; } @Override public List<String> getSupportedRealms() { return supportedRealms; } @Override public String getHandlerRealm() { return realm; } public void setAttributeFileLocation(String attributeFileLocation) { this.attributeFileLocation = attributeFileLocation; } }