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