1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package edu.internet2.middleware.shibboleth.common.attribute.provider;
18
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25
26 import org.opensaml.Configuration;
27 import org.opensaml.common.SAMLObject;
28 import org.opensaml.common.SAMLObjectBuilder;
29 import org.opensaml.saml1.core.Attribute;
30 import org.opensaml.saml1.core.AttributeDesignator;
31 import org.opensaml.saml1.core.AttributeQuery;
32 import org.opensaml.saml1.core.AttributeStatement;
33 import org.opensaml.saml1.core.NameIdentifier;
34 import org.opensaml.saml1.core.ResponseAbstractType;
35 import org.opensaml.saml2.metadata.EntityDescriptor;
36 import org.opensaml.xml.XMLObjectBuilderFactory;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39 import org.springframework.context.ApplicationContext;
40
41 import edu.internet2.middleware.shibboleth.common.attribute.AttributeRequestException;
42 import edu.internet2.middleware.shibboleth.common.attribute.BaseAttribute;
43 import edu.internet2.middleware.shibboleth.common.attribute.encoding.AttributeEncoder;
44 import edu.internet2.middleware.shibboleth.common.attribute.encoding.AttributeEncodingException;
45 import edu.internet2.middleware.shibboleth.common.attribute.encoding.SAML1AttributeEncoder;
46 import edu.internet2.middleware.shibboleth.common.attribute.filtering.provider.ShibbolethAttributeFilteringEngine;
47 import edu.internet2.middleware.shibboleth.common.attribute.resolver.provider.ShibbolethAttributeResolver;
48 import edu.internet2.middleware.shibboleth.common.config.BaseService;
49 import edu.internet2.middleware.shibboleth.common.profile.provider.SAMLProfileRequestContext;
50 import edu.internet2.middleware.shibboleth.common.relyingparty.provider.saml1.AbstractSAML1ProfileConfiguration;
51 import edu.internet2.middleware.shibboleth.common.service.ServiceException;
52
53
54
55
56 public class ShibbolethSAML1AttributeAuthority extends BaseService implements SAML1AttributeAuthority {
57
58
59 private final Logger log = LoggerFactory.getLogger(ShibbolethSAML1AttributeAuthority.class);
60
61
62 private SAMLObjectBuilder<AttributeStatement> statementBuilder;
63
64
65 private ShibbolethAttributeResolver attributeResolver;
66
67
68 private ShibbolethAttributeFilteringEngine filteringEngine;
69
70
71
72
73
74
75 @SuppressWarnings("unchecked")
76 public ShibbolethSAML1AttributeAuthority(ShibbolethAttributeResolver resolver) {
77
78 XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
79 statementBuilder = (SAMLObjectBuilder<AttributeStatement>) builderFactory
80 .getBuilder(AttributeStatement.DEFAULT_ELEMENT_NAME);
81
82 attributeResolver = resolver;
83 }
84
85
86
87
88
89
90 public ShibbolethAttributeResolver getAttributeResolver() {
91 return attributeResolver;
92 }
93
94
95
96
97
98
99 public ShibbolethAttributeFilteringEngine getFilteringEngine() {
100 return filteringEngine;
101 }
102
103
104
105
106
107
108 public void setFilteringEngine(ShibbolethAttributeFilteringEngine engine) {
109 filteringEngine = engine;
110 }
111
112
113 public AttributeStatement buildAttributeStatement(AttributeQuery query, Collection<BaseAttribute> attributes)
114 throws AttributeEncodingException {
115
116 Collection<Attribute> encodedAttributes = encodeAttributes(attributes);
117 if (encodedAttributes != null && !encodedAttributes.isEmpty()) {
118 AttributeStatement statement = statementBuilder.buildObject();
119 statement.getAttributes().addAll(encodedAttributes);
120 return statement;
121 } else {
122 log.debug("No attributes were encoded, no attribute statement created.");
123 return null;
124 }
125 }
126
127
128 public String getAttributeIDBySAMLAttribute(AttributeDesignator attribute) {
129
130 return null;
131 }
132
133
134 public String getPrincipal(
135 SAMLProfileRequestContext<? extends SAMLObject, ? extends ResponseAbstractType, NameIdentifier, ? extends AbstractSAML1ProfileConfiguration> requestContext)
136 throws AttributeRequestException {
137 if (requestContext.getInboundMessageIssuer() == null || requestContext.getSubjectNameIdentifier() == null) {
138 throw new AttributeRequestException(
139 "Unable to resolve principal, attribute requester ID and subject name identifier may not be null");
140 }
141 return attributeResolver.resolvePrincipalName(requestContext);
142 }
143
144
145 public AttributeDesignator getSAMLAttributeByAttributeID(String id) {
146
147 return null;
148 }
149
150
151 public Map<String, BaseAttribute> getAttributes(
152 SAMLProfileRequestContext<? extends SAMLObject, ? extends ResponseAbstractType, NameIdentifier, ? extends AbstractSAML1ProfileConfiguration> requestContext)
153 throws AttributeRequestException {
154 HashSet<String> requestedAttributes = new HashSet<String>();
155
156
157 Set<String> queryAttributeIds = getAttributeIds(requestContext.getInboundSAMLMessage());
158 requestedAttributes.addAll(queryAttributeIds);
159
160
161 Set<String> metadataAttributeIds = getAttribtueIds(requestContext.getPeerEntityMetadata());
162 requestedAttributes.addAll(metadataAttributeIds);
163
164 requestContext.setRequestedAttributes(requestedAttributes);
165
166 Map<String, BaseAttribute> attributes = attributeResolver.resolveAttributes(requestContext);
167
168 if (filteringEngine != null) {
169 attributes = filteringEngine.filterAttributes(attributes, requestContext);
170 }
171
172 return attributes;
173 }
174
175
176
177
178
179
180
181
182 protected Set<String> getAttributeIds(SAMLObject samlRequest) {
183 Set<String> queryAttributeIds = new HashSet<String>();
184 if (!(samlRequest instanceof AttributeQuery)) {
185 return queryAttributeIds;
186 }
187
188 AttributeQuery query = (AttributeQuery) samlRequest;
189 if (query != null) {
190 List<AttributeDesignator> queryAttributes = query.getAttributeDesignators();
191 queryAttributeIds = getAttributeIds(queryAttributes);
192 log.debug("query message contains the following attributes: {}", queryAttributeIds);
193 }
194
195 return queryAttributeIds;
196 }
197
198
199
200
201
202
203
204
205 protected Set<String> getAttribtueIds(EntityDescriptor metadata) {
206 Set<String> metadataAttributeIds = new HashSet<String>();
207
208 return metadataAttributeIds;
209 }
210
211
212
213
214
215
216
217 protected Set<String> getAttributeIds(List<AttributeDesignator> attributes) {
218 final Set<String> attributeIds = new HashSet<String>();
219 for (AttributeDesignator a : attributes) {
220 String attrId = getAttributeIDBySAMLAttribute(a);
221 attributeIds.add(attrId);
222 }
223 return attributeIds;
224 }
225
226
227
228
229
230
231
232
233 @SuppressWarnings("unchecked")
234 protected Collection<Attribute> encodeAttributes(Collection<BaseAttribute> attributes) {
235 Collection<Attribute> encodedAttributes = new ArrayList<Attribute>();
236
237 boolean attributeEncoded = false;
238
239 for (BaseAttribute<?> shibbolethAttribute : attributes) {
240 if (shibbolethAttribute.getValues() == null || shibbolethAttribute.getValues().size() == 0) {
241 continue;
242 }
243
244
245 Attribute attribute;
246 for (AttributeEncoder encoder : shibbolethAttribute.getEncoders()) {
247 if (encoder instanceof SAML1AttributeEncoder) {
248 try {
249 attribute = (Attribute) encoder.encode(shibbolethAttribute);
250 if (attribute != null) {
251 encodedAttributes.add(attribute);
252 attributeEncoded = true;
253 if (log.isDebugEnabled()) {
254 log.debug("Encoded attribute {} with encoder of type {}", shibbolethAttribute.getId(),
255 encoder.getClass().getName());
256 }
257 }
258 } catch (AttributeEncodingException e) {
259 log.warn("Unable to encode attribute: {}", shibbolethAttribute.getId(), e);
260 }
261 }
262 }
263
264
265 if (!attributeEncoded) {
266 log.debug("Attribute {} was not encoded because no SAML1AttributeEncoder was attached to it.",
267 shibbolethAttribute.getId());
268 }
269 }
270
271 return encodedAttributes;
272 }
273
274
275 protected void onNewContextCreated(ApplicationContext newServiceContext) throws ServiceException {
276
277 }
278 }