Spring SAML - Lendo e atualizando metadados do IdP em tempo de execução
Estou usando o WSO2 e o SSOCircle com a extensão Spring-SAML. No momento, estamos testando configurações e definimos 2 IdPs e 2 SPs em nosso applicationContext. Portanto, atualmente, temos 2 IdPs estaticamente definidos em nossa configuração xml da primavera e isso está funcionando. Para fins de teste, estamos usando a combinação de CachingMetadataManager e ResourceBackedMetadataProvider para que os metadados do IdP sejam criados dentro do nosso arquivo WAR. Amostra:
<bean id="metadata" class="org.springframework.security.saml.metadata.CachingMetadataManager">
<constructor-arg>
<list>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean class="org.opensaml.saml2.metadata.provider.ResourceBackedMetadataProvider">
<constructor-arg>
<bean class="java.util.Timer"/>
</constructor-arg>
<constructor-arg>
<bean class="org.opensaml.util.resource.ClasspathResource">
<c,onstructor-arg value="/metadata/wso2idp_metadata.xml"/>
</bean>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
</bean>
</constructor-arg>
</bean>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean class="org.opensaml.saml2.metadata.provider.ResourceBackedMetadataProvider">
<constructor-arg>
<bean class="java.util.Timer"/>
</constructor-arg>
<constructor-arg>
<bean class="org.opensaml.util.resource.ClasspathResource">
<constructor-arg value="/metadata/ssocircleidp_metadata.xml"/>
</bean>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
</bean>
</constructor-arg>
</bean>
</list>
</constructor-arg>
Para produção, queremos poder armazenar nossos metadados de IdP em um banco de dados (localizado centralmente). Quero poder adicionar, remover e modificar os metadados sem reimplementar o WAR ou reiniciar o (s) servidor (es). Inicialmente, pensei em substituir o CachingMetadataManager e definir um construtor noarg que pudesse carregar dinamicamente todos os provedores de metadados, mas isso não é possível porque o CachingMetadataManager define apenas um construtor que deve incluir uma lista de metadadosProvider. Acabei fazendo o seguinte:
<bean id="metadataList" class="org.arbfile.util.security.saml.DBMetadataProviderList">
<constructor-arg ref="parserPool" />
<constructor-arg>
<bean class="java.util.Timer"/>
</constructor-arg>
</bean>
<bean id="metadata" class="org.springframework.security.saml.metadata.CachingMetadataManager">
<constructor-arg ref="metadataList" />
</bean>
Os metadataList do bean podem ser definidos simplesmente como:
public final class DBMetadataProviderList extends ArrayList<MetadataProvider>
{
private final static Logger log = LoggerFactory.getLogger(DBMetadataProviderList.class);
private ParserPool parser;
public DBMetadataProviderList(ParserPool _parser, Timer _timer) throws MetadataProviderException
{
this.parser = _parser;
// Lookup metadata from DB
}
}
Isso me permite ler os metadados do IdP dinamicamente. Minha lógica cai quando se trata de refrescar embora. eu encontreieste post no fórum da primavera, no entanto, tem 3 a 4 anos de idade. Qual é a melhor maneira de ler, adicionar e atualizar dinamicamente os metadados do IdP, armazená-los em cache e atualizar o cache em algum intervalo? No meu caso, uma linha em uma tabela do banco de dados seria equivalente a uma única definição de metadados do IdP.