diff --git a/.gitignore b/.gitignore index a825272..c0ecef6 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ pmd.spec *_sstub.c .deps .libs +.rpm +rpms # autoconf @@ -46,6 +48,7 @@ ar-lib /server/pmd /tools/cli/pmd-cli /privsep/pmdprivsepd +/tools/pmd.spec build/* # Object files diff --git a/Makefile.am b/Makefile.am index be70c9d..82331b7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ CLEANFILES = EXTRA_DIST = noinst_DATA = conf_DATA = conf/pmd.conf -pkginclude_HEADERS = include/pmd.h include/pmdtypes.h include/pmderror.h +pkginclude_HEADERS = include/pmd.h include/pmdtypes.h include/pmderror.h include/roleplugin.h pkgconfigdir = $(libdir)/pkgconfig SUBDIRS = \ diff --git a/client/Makefile.am b/client/Makefile.am index ebe0249..a29ec47 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -17,6 +17,8 @@ libpmdclient_la_SOURCES = \ pmd_cstub.c \ netmgmt_cstub.c \ netmgr_api.c \ + rolemgmt_api.c \ + rolemgmt_cstub.c \ usermgmt_api.c \ usermgmt_cstub.c \ usermgmt_rpc_misc.c \ @@ -50,6 +52,9 @@ netmgmt_cstub.c: cp ../idl/netmgmt_cstub.c . +rolemgmt_cstub.c: + cp ../idl/rolemgmt_cstub.c . + usermgmt_cstub.c: cp ../idl/usermgmt_cstub.c . @@ -80,14 +85,17 @@ CLEANFILES = \ pkgmgmt_privsep_cstub.c \ netgmgmt_privsep_cstub.c \ fwgmgmt_privsep_cstub.c \ - usergmgmt_privsep_cstub.c + usergmgmt_privsep_cstub.c \ + rolemgmt_cstub.c \ + rpmostree_cstub.c libpmdclient_la_LIBADD = \ @top_builddir@/common/libcommon.la \ @DCERPC_LIBS@ \ @LWBASE_LIBS@ \ - -lpthread + -lpthread \ + -llwbase_nothr libpmdclient_la_LDFLAGS= \ - @DCERPC_LDFLAGS@ \ - @LW_LDFLAGS@ + @LW_LDFLAGS@ \ + @DCERPC_LDFLAGS@ diff --git a/client/includes.h b/client/includes.h index b5fb89f..5726ef6 100644 --- a/client/includes.h +++ b/client/includes.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -11,7 +11,6 @@ * License for the specific language governing permissions and limitations * under the License. */ - #pragma once #include @@ -20,7 +19,6 @@ #include #include #include - #include #include #include @@ -32,6 +30,8 @@ #include "../idl/pkgmgmt_h.h" #include "../idl/pmd_h.h" #include "../idl/netmgmt_h.h" +#include "../idl/rolemgmt_h.h" +#include "../idl/rpmostree_h.h" #include "../idl/usermgmt_h.h" #include "../idl/privsepd_h.h" diff --git a/client/pkgmgmt_api.c b/client/pkgmgmt_api.c index 0ce8868..3b0a75b 100644 --- a/client/pkgmgmt_api.c +++ b/client/pkgmgmt_api.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" uint32_t diff --git a/client/rolemgmt_api.c b/client/rolemgmt_api.c index 1b3a9c7..ff6e5f8 100644 --- a/client/rolemgmt_api.c +++ b/client/rolemgmt_api.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" uint32_t @@ -84,9 +83,17 @@ rolemgmt_get_roles( (void **)&pRole); BAIL_ON_PMD_ERROR(dwError); + dwError = PMDAllocateStringAFromW( + pRoleArray->pRoles[i].pwszId, + &pRole->pszId); + BAIL_ON_PMD_ERROR(dwError); + dwError = PMDAllocateStringAFromW( + pRoleArray->pRoles[i].pwszName, + &pRole->pszName); + BAIL_ON_PMD_ERROR(dwError); dwError = PMDAllocateStringAFromW( - pRoleArray->pRoles[i].pwszRole, - &pRole->pszRole); + pRoleArray->pRoles[i].pwszDescription, + &pRole->pszDescription); BAIL_ON_PMD_ERROR(dwError); if(!pTail) { @@ -102,7 +109,9 @@ rolemgmt_get_roles( } *ppRoles = pRoles; + cleanup: + PMDRpcClientFreeMemory(pRoleArray); return dwError; error: @@ -110,5 +119,341 @@ rolemgmt_get_roles( { *ppRoles = NULL; } + rolemgmt_free_roles(pRoles); + rolemgmt_free_roles(pRole); + goto cleanup; +} + +uint32_t +rolemgmt_get_role_version( + PPMDHANDLE hHandle, + const char *pszName, + char **ppszVersion + ) +{ + uint32_t dwError = 0; + char *pszVersion = NULL; + wstring_t pwszVersion = NULL; + wstring_t pwszName = NULL; + + if(!hHandle || IsNullOrEmptyString(pszName) || !ppszVersion) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateStringWFromA( + pszName, + &pwszName); + BAIL_ON_PMD_ERROR(dwError); + + DO_RPC(rolemgmt_rpc_role_version(hHandle->hRpc, pwszName, &pwszVersion), + dwError); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateStringAFromW( + pwszVersion, + &pszVersion); + BAIL_ON_PMD_ERROR(dwError); + + *ppszVersion = pszVersion; + +cleanup: + PMD_SAFE_FREE_MEMORY(pwszName); + PMDRpcClientFreeStringW(pwszVersion); + return dwError; + +error: + if(ppszVersion) + { + *ppszVersion = NULL; + } + PMD_SAFE_FREE_MEMORY(pszVersion); + goto cleanup; +} + +uint32_t +rolemgmt_get_prereqs( + PPMDHANDLE hHandle, + const char *pszName, + PMD_ROLE_OPERATION nOperation, + PPMD_ROLE_PREREQ *ppPrereqs, + uint32_t *pdwPrereqCount + ) +{ + uint32_t dwError = 0; + uint32_t i = 0; + wstring_t pwszName = NULL; + PPMD_RPC_ROLEMGMT_PREREQ_ARRAY pPrereqArray = NULL; + PPMD_ROLE_PREREQ pPrereqs = NULL; + uint32_t dwPrereqCount = 0; + + if(!hHandle || IsNullOrEmptyString(pszName) || !ppPrereqs || !pdwPrereqCount) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateStringWFromA( + pszName, + &pwszName); + BAIL_ON_PMD_ERROR(dwError); + + DO_RPC(rolemgmt_rpc_role_get_prereqs( + hHandle->hRpc, + pwszName, + nOperation, + &pPrereqArray), + dwError); + BAIL_ON_PMD_ERROR(dwError); + + dwPrereqCount = pPrereqArray ? pPrereqArray->dwCount : 0; + if(!dwPrereqCount) + { + dwError = ERROR_PMD_NO_DATA; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateMemory( + sizeof(PMD_ROLE_PREREQ) * dwPrereqCount, + (void **)&pPrereqs); + BAIL_ON_PMD_ERROR(dwError); + + for(i = 0; i < dwPrereqCount; ++i) + { + dwError = PMDAllocateStringAFromW( + pPrereqArray->pPrereqs[i].pwszName, + &pPrereqs[i].pszName); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateStringAFromW( + pPrereqArray->pPrereqs[i].pwszDescription, + &pPrereqs[i].pszDescription); + BAIL_ON_PMD_ERROR(dwError); + } + + *ppPrereqs = pPrereqs; + *pdwPrereqCount = dwPrereqCount; + +cleanup: + PMD_SAFE_FREE_MEMORY(pwszName); + return dwError; + +error: + if(ppPrereqs) + { + *ppPrereqs = NULL; + } + goto cleanup; +} + +uint32_t +rolemgmt_alter( + PPMDHANDLE hHandle, + const char *pszName, + int nOperation, + const char *pszConfigJson, + char **ppszTaskUUID + ) +{ + uint32_t dwError = 0; + wstring_t pwszName = NULL; + wstring_t pwszTaskUUID = NULL; + wstring_t pwszConfigJson = NULL; + char *pszTaskUUID = NULL; + + if(!hHandle || + IsNullOrEmptyString(pszName) || + !ppszTaskUUID) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if(nOperation == ROLE_OPERATION_ENABLE && + IsNullOrEmptyString(pszConfigJson)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if(IsNullOrEmptyString(pszConfigJson)) + { + pszConfigJson = "{}"; + } + + + dwError = PMDAllocateStringWFromA( + pszName, + &pwszName); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateStringWFromA( + pszConfigJson, + &pwszConfigJson); + BAIL_ON_PMD_ERROR(dwError); + + DO_RPC(rolemgmt_rpc_role_alter( + hHandle->hRpc, + pwszName, + nOperation, + pwszConfigJson, + &pwszTaskUUID + ), + dwError); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateStringAFromW( + pwszTaskUUID, + &pszTaskUUID); + BAIL_ON_PMD_ERROR(dwError); + + *ppszTaskUUID = pszTaskUUID; + +cleanup: + PMD_SAFE_FREE_MEMORY(pwszName); + PMD_SAFE_FREE_MEMORY(pwszConfigJson); + PMDRpcClientFreeStringW(pwszTaskUUID); + return dwError; + +error: + if(ppszTaskUUID) + { + *ppszTaskUUID = NULL; + } + PMD_SAFE_FREE_MEMORY(pszTaskUUID); + goto cleanup; +} + +uint32_t +rolemgmt_get_status( + PPMDHANDLE hHandle, + const char *pszName, + const char *pszTaskUUID, + PMD_ROLE_STATUS *pnStatus + ) +{ + uint32_t dwError = 0; + wstring_t pwszName = NULL; + wstring_t pwszTaskUUID = NULL; + RPC_ROLE_STATUS nStatus = ROLE_STATUS_NONE; + + if(!hHandle || + IsNullOrEmptyString(pszName) || + IsNullOrEmptyString(pszTaskUUID) || + !pnStatus) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateStringWFromA( + pszName, + &pwszName); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateStringWFromA( + pszTaskUUID, + &pwszTaskUUID); + BAIL_ON_PMD_ERROR(dwError); + + DO_RPC(rolemgmt_rpc_role_get_status( + hHandle->hRpc, + pwszName, + pwszTaskUUID, + &nStatus), + dwError); + BAIL_ON_PMD_ERROR(dwError); + + *pnStatus = nStatus; + +cleanup: + return dwError; + +error: + if(pnStatus) + { + dwError = ROLE_STATUS_NONE; + } + goto cleanup; +} + +uint32_t +rolemgmt_get_log( + PPMDHANDLE hHandle, + const char *pszTaskUUID, + uint32_t dwOffset, + uint32_t dwEntriesToFetch, + PPMD_ROLEMGMT_TASK_LOG *ppTaskLogs, + uint32_t *pdwTaskLogCount + ) +{ + uint32_t dwError = 0; + uint32_t dwTaskLogCount = 0; + uint32_t i = 0; + wstring_t pwszTaskUUID = NULL; + PPMD_RPC_ROLEMGMT_TASK_LOG_ARRAY pTaskLogArray = NULL; + PPMD_ROLEMGMT_TASK_LOG pTaskLogs = NULL; + + if(!hHandle || + IsNullOrEmptyString(pszTaskUUID) || + !ppTaskLogs || + !pdwTaskLogCount) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateStringWFromA( + pszTaskUUID, + &pwszTaskUUID); + BAIL_ON_PMD_ERROR(dwError); + + DO_RPC(rolemgmt_rpc_role_get_log( + hHandle->hRpc, + pwszTaskUUID, + dwOffset, + dwEntriesToFetch, + &pTaskLogArray), + dwError); + BAIL_ON_PMD_ERROR(dwError); + + dwTaskLogCount = pTaskLogArray ? pTaskLogArray->dwCount : 0; + if(!dwTaskLogCount) + { + dwError = ERROR_PMD_NO_DATA; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateMemory( + sizeof(PMD_ROLEMGMT_TASK_LOG) * dwTaskLogCount, + (void **)&pTaskLogs); + BAIL_ON_PMD_ERROR(dwError); + + for(i = 0; i < dwTaskLogCount; ++i) + { + pTaskLogs[i].tStamp = pTaskLogArray->pTaskLogs[i].tStamp; + dwError = PMDAllocateStringAFromW( + pTaskLogArray->pTaskLogs[i].pwszLog, + &pTaskLogs[i].pszLog); + BAIL_ON_PMD_ERROR(dwError); + } + + *ppTaskLogs = pTaskLogs; + *pdwTaskLogCount = dwTaskLogCount; + +cleanup: + PMD_SAFE_FREE_MEMORY(pwszTaskUUID); + return dwError; + +error: + if(ppTaskLogs) + { + *ppTaskLogs = NULL; + } + if(pdwTaskLogCount) + { + *pdwTaskLogCount = 0; + } goto cleanup; } diff --git a/client/rpc.c b/client/rpc.c index 892cea6..1d02c24 100644 --- a/client/rpc.c +++ b/client/rpc.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -293,6 +293,7 @@ rpc_open( {"pmd", pmd_v1_0_c_ifspec}, {"net", netmgmt_v1_0_c_ifspec}, {"usermgmt", usermgmt_v1_0_c_ifspec}, + {"rolemgmt", rolemgmt_v1_0_c_ifspec}, }; int nNumKnownIfspecs = diff --git a/common/Makefile.am b/common/Makefile.am index a905f75..ac33146 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -18,5 +18,8 @@ libcommon_la_CPPFLAGS = \ @LW_INCLUDES@ libcommon_la_LDFLAGS = \ + @DCERPC_LIBS@ \ @LIBCURL_LIBS@ \ + -lpthread \ + -llwbase_nothr \ -static diff --git a/common/configreader.c b/common/configreader.c index 96b621b..5cf6732 100644 --- a/common/configreader.c +++ b/common/configreader.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" uint32_t conf_section_default( @@ -207,6 +206,7 @@ free_config_data( return; } free_config_sections(pData->pSections); + PMD_SAFE_FREE_MEMORY(pData->pszConfFile); PMD_SAFE_FREE_MEMORY(pData); } @@ -356,6 +356,7 @@ process_config_line( { uint32_t dwError = 0; int nSection = 0; + char *pszSection = NULL; if(IsNullOrEmptyString(pszLine) || !pData) { @@ -369,7 +370,6 @@ process_config_line( if(nSection && pfnConfSectionCB) { char *pszSection = NULL; - dwError = get_section(pszLine, &pszSection); BAIL_ON_PMD_ERROR(dwError); @@ -386,6 +386,7 @@ process_config_line( } cleanup: + PMD_SAFE_FREE_MEMORY(pszSection); return dwError; error: @@ -418,9 +419,11 @@ read_config_file( BAIL_ON_PMD_ERROR(dwError); } - pData = calloc(sizeof(CONF_DATA), 1); - pData->pszConfFile = calloc(strlen(pszFile) + 1, sizeof(char)); - strcpy(pData->pszConfFile, pszFile); + dwError = PMDAllocateMemory(sizeof(CONF_DATA), (void **)&pData); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateString(pszFile, &pData->pszConfFile); + BAIL_ON_PMD_ERROR(dwError); nMaxLineLength = nLineLength > MAX_CONFIG_LINE_LENGTH ? nLineLength : MAX_CONFIG_LINE_LENGTH; diff --git a/common/defines.h b/common/defines.h index 765226d..ff01acb 100644 --- a/common/defines.h +++ b/common/defines.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #pragma once #ifndef PMD_WSTRING_DEFINED @@ -64,6 +63,13 @@ typedef unsigned short* wstring_t; } \ } while(0) +#define PMD_RPCSRV_SAFE_FREE_MEMORY(pMemory) \ + do { \ + if (pMemory) { \ + PMDRpcServerFreeMemory(pMemory); \ + } \ + } while(0) + #define PMD_UNKNOWN_ERROR_STRING "Unknown error" #define PMD_ERROR_TABLE \ { \ @@ -76,4 +82,13 @@ typedef unsigned short* wstring_t; {ERROR_PMD_PRIVSEP_ENCRYPT, "ERROR_PMD_PRIVSEP_ENCRYPT", "There was an error encrypting information for privilege separation. Please check privilege separation keys."}, \ {ERROR_PMD_PRIVSEP_DECRYPT, "ERROR_PMD_PRIVSEP_DECRYPT", "There was an error decrypting information for privilege separation. Please check privilege separation keys."}, \ {ERROR_PMD_INVALID_CMD, "ERROR_PMD_INVALID_CMD", "Invalid command."}, \ + {ERROR_PMD_NOTHING_TO_DO, "ERROR_PMD_NOTHING_TO_DO", "Nothing to do."}, \ + {ERROR_PMD_ROLES_PLUGIN_NOT_SET,"ERROR_PMD_ROLES_PLUGIN_NOT_SET","Plugin is not set for this role."}, \ + {ERROR_PMD_ROLE_UNMAPPED_FN, "ERROR_PMD_ROLE_UNMAPPED_FN", "Plugin is loaded but does not specify an entry point for this functionality."}, \ + {ERROR_PMD_ROLE_UNMAPPED_LOAD, "ERROR_PMD_ROLE_UNMAPPED_LOAD", "Plugin is loaded but does not specify an entry point for javelin_role_load."}, \ + {ERROR_PMD_ROLE_PLUGIN_BAD, "ERROR_PMD_ROLE_PLUGIN_BAD", "Plugin is loaded but did not behave as expected. Plugin has been disabled for this session."}, \ + {ERROR_PMD_ROLE_PLUGIN_DISABLED,"ERROR_PMD_ROLE_PLUGIN_DISABLED","Plugin is disabled. Most likely cause is an unexpected response from plugin apis. Restarting the server will reload plugins."}, \ + {ERROR_PMD_ROLE_PLUGIN_HAS_TASKS,"ERROR_PMD_ROLE_PLUGIN_HAS_TASKS","Plugin has tasks. Please use status to get a status on tasks. Cannot queue another task at this time."}, \ + {ERROR_PMD_ROLE_TASK_NOT_FOUND, "ERROR_PMD_ROLE_TASK_NOT_FOUND", "Could not find a task matching the id provided."}, \ + {ERROR_PMD_ROLE_TASK_NO_LOGS, "ERROR_PMD_ROLE_TASK_NO_LOGS", "Task has no logs."}, \ }; diff --git a/common/includes.h b/common/includes.h index 4371e3f..f0691dd 100644 --- a/common/includes.h +++ b/common/includes.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -35,11 +35,11 @@ #include #include - +#include #include "defines.h" #include "structs.h" #include "prototypes.h" - +#include "../server/defines.h" #include #include #include diff --git a/common/prototypes.h b/common/prototypes.h index ddc90d2..4734ae8 100644 --- a/common/prototypes.h +++ b/common/prototypes.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #pragma once uint32_t @@ -33,6 +32,12 @@ PMDAllocateStringWFromA( wstring_t* ppwszDst ); +uint32_t +PMDSafeAllocateString( + const char* pszSrc, + char** ppszDest + ); + uint32_t PMDAllocateString( const char* pszSrc, @@ -242,6 +247,13 @@ uint32_t validate_cmd( const char *pszCmd ); +uint32_t +isStringPrefix( + char *pszString, + char *pszPrefix, + int *result + ); + //rpcsrvutils.c uint32_t PMDRpcServerAllocateMemory( diff --git a/common/rolemgmt.c b/common/rolemgmt.c index 7064c45..eb290bd 100644 --- a/common/rolemgmt.c +++ b/common/rolemgmt.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,19 +12,161 @@ * under the License. */ - #include "includes.h" +void +rolemgmt_free_role( + PPMD_ROLEMGMT_ROLE pRole + ); + +uint32_t +rolemgmt_status_from_string( + const char *pszStatus, + PMD_ROLE_STATUS *pnStatus + ) +{ + uint32_t dwError = 0; + size_t nSize = 0; + size_t i = 0; + PMD_ROLE_STATUS nStatus = ROLE_STATUS_NONE; + struct stLookup + { + PMD_ROLE_STATUS nStatus; + const char *pszStatus; + }arLookup[] = + { + {ROLE_STATUS_SUCCESS, "success"}, + {ROLE_STATUS_FAILURE, "failure"}, + {ROLE_STATUS_NOT_STARTED, "not started"}, + {ROLE_STATUS_IN_PROGRESS, "in progress"} + }; + nSize = sizeof(arLookup)/sizeof(arLookup[0]); + + if(!pszStatus || !pnStatus) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + for(i = 0; i < nSize; ++i) + { + if(!strcmp(pszStatus, arLookup[i].pszStatus)) + { + nStatus = arLookup[i].nStatus; + break; + } + } + + if(nStatus == ROLE_STATUS_NONE) + { + dwError = ERROR_PMD_ROLE_BAD_STATUS; + BAIL_ON_PMD_ERROR(dwError); + } + + *pnStatus= nStatus; + +cleanup: + return dwError; + +error: + if(pnStatus) + { + *pnStatus = ROLE_STATUS_NONE; + } + goto cleanup; +} + +uint32_t +rolemgmt_status_to_string( + PMD_ROLE_STATUS nStatus, + char **ppszStatus + ) +{ + uint32_t dwError = 0; + char *pszStatus = NULL; + size_t nSize = 0; + char *pszStrings[] = + { + "none", + "success", + "failure", + "not started" + "in progress" + }; + nSize = sizeof(pszStrings)/sizeof(pszStrings[0]); + + if(nStatus <= ROLE_STATUS_NONE || + nStatus > nSize || + !ppszStatus) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateString(pszStrings[nStatus], &pszStatus); + BAIL_ON_PMD_ERROR(dwError); + + *ppszStatus = pszStatus; + +cleanup: + return dwError; + +error: + if(ppszStatus) + { + *ppszStatus = NULL; + } + PMD_SAFE_FREE_MEMORY(pszStatus); + goto cleanup; +} + + +void +rolemgmt_free_children( + PPMD_ROLEMGMT_ROLE pRole + ) +{ + int i = 0; + for(i = 0; i < pRole->nChildCount; ++i) + { + rolemgmt_free_role(pRole->ppChildren[i]); + } + PMD_SAFE_FREE_MEMORY(pRole->ppChildren); +} + +void +rolemgmt_free_role( + PPMD_ROLEMGMT_ROLE pRole + ) +{ + int i = 0; + if(!pRole) + { + return; + } + PMD_SAFE_FREE_MEMORY(pRole->pszName); + PMD_SAFE_FREE_MEMORY(pRole->pszParent); + PMD_SAFE_FREE_MEMORY(pRole->pszDisplayName); + PMD_SAFE_FREE_MEMORY(pRole->pszDescription); + PMD_SAFE_FREE_MEMORY(pRole->pszPlugin); + rolemgmt_free_children(pRole); + PMDFreeMemory(pRole); +} + void rolemgmt_free_roles( PPMD_ROLEMGMT_ROLE pRoles ) { + if(!pRoles) + { + return; + } + PPMD_ROLEMGMT_ROLE pRole = NULL; while(pRoles) { - PPMD_ROLEMGMT_ROLE pRole = pRoles->pNext; - PMD_SAFE_FREE_MEMORY(pRoles->pszRole); - PMD_SAFE_FREE_MEMORY(pRoles); + pRole = pRoles->pNext; + rolemgmt_free_role(pRoles); pRoles = pRole; } } diff --git a/common/strings.c b/common/strings.c index 47e15a0..f042607 100644 --- a/common/strings.c +++ b/common/strings.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,9 +12,22 @@ * under the License. */ - #include "includes.h" +uint32_t +PMDSafeAllocateString( + const char *pszSrc, + char **ppszDest + ) +{ + if(!pszSrc && ppszDest) + { + *ppszDest = NULL; + return 0; + } + return PMDAllocateString(pszSrc, ppszDest); +} + uint32_t PMDGetStringLengthW( const wstring_t pwszStr, diff --git a/common/utils.c b/common/utils.c index faf321b..7718786 100644 --- a/common/utils.c +++ b/common/utils.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -125,7 +125,7 @@ file_read_all_text( if(!fp) { dwError = ENOENT; - BAIL_ON_PMD_ERROR(dwError); + BAIL_ON_PMD_SYSTEM_ERROR(dwError); } fseek(fp, 0, SEEK_END); nLength = ftell(fp); @@ -1191,3 +1191,37 @@ base64_get_user_pass( PMD_SAFE_FREE_MEMORY(pszPass); goto cleanup; } + +uint32_t +isStringPrefix( + char *pszString, + char *pszPrefix, + int *pnResult + ) +{ + uint32_t dwError = 0; + uint32_t nPrefixLen = 0, nStrLen = 0; + if(pnResult == NULL || IsNullOrEmptyString(pszPrefix) || IsNullOrEmptyString(pszString)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + *pnResult = 0; + nPrefixLen = strlen(pszPrefix); + nStrLen = strlen(pszString); + + if(nStrLen <= nPrefixLen) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if(!strncmp(pszString, pszPrefix, nPrefixLen)) + { + *pnResult = 1; + } +cleanup: + return dwError; +error: + goto cleanup; +} diff --git a/conf/example.role b/conf/example.role new file mode 100644 index 0000000..5948ccb --- /dev/null +++ b/conf/example.role @@ -0,0 +1,3 @@ +[example_role] +name=example role +description=example role that does nothing diff --git a/conf/pmd.conf b/conf/pmd.conf index f622385..42dcc2c 100644 --- a/conf/pmd.conf +++ b/conf/pmd.conf @@ -2,8 +2,12 @@ #not an rpmostree server servertype=0 apisecurity=/etc/pmd/api_sddl.conf -roledir=/etc/javelin.roles.d -rolepluginsdir=/etc/javelin.roles.plugins.d +roledir=/etc/pmd.roles.d +rolepluginsdir=/etc/pmd.roles.plugins.d + +[roles] +dir=/etc/pmd.roles.d +pluginsdir=/etc/pmd.roles.plugins.d [rest-server] enabled=1 diff --git a/conf/restapispec.json b/conf/restapispec.json index 538ebb6..f542a96 100644 --- a/conf/restapispec.json +++ b/conf/restapispec.json @@ -2,9 +2,9 @@ "swagger":"2.0", "info": { - "description":"Javelin allows secure remote resource management for PhotonOS.", + "description":"PMD allows secure remote resource management for PhotonOS.", "version":"0.9", - "title":"Javelin", + "title":"PMD", "contact":{"email":"photon-core-dev.eng.vmware.com"}, "license": { @@ -23,7 +23,7 @@ "externalDocs": { "description":"Find out more", - "url":"http://wiki.eng.vmware.com/Photon/Javelin" + "url":"https://github.com/vmware/pmd" } }, { @@ -32,7 +32,7 @@ "externalDocs": { "description":"Find out more", - "url":"http://wiki.eng.vmware.com/Photon/Javelin" + "url":"https://github.com/vmware/pmd" } }, { @@ -41,7 +41,7 @@ "externalDocs": { "description":"Find out more", - "url":"http://wiki.eng.vmware.com/Photon/Javelin" + "url":"https://github.com/vmware/pmd" } }, { @@ -50,7 +50,7 @@ "externalDocs": { "description":"Find out more", - "url":"http://wiki.eng.vmware.com/Photon/Javelin" + "url":"https://github.com/vmware/pmd" } }, { @@ -59,7 +59,16 @@ "externalDocs": { "description":"Find out more", - "url":"http://wiki.eng.vmware.com/Photon/Javelin" + "url":"https://github.com/vmware/pmd" + } + }, + { + "name":"rolemgmt", + "description":"role management module", + "externalDocs": + { + "description":"Find out more", + "url":"https://github.com/vmware/pmd" } } ], @@ -1862,6 +1871,226 @@ "responses":{"200":{"result":"success"}}, "security":[] } + }, + "/rolemgmt/version": + { + "get": + { + "tags":["rolemgmt"], + "summary":"get rolemgmt version", + "description":"get rolemgmt version", + "operationId":"get_rolemgmt_version", + "consumes":[], + "produces":["application/json"], + "parameters":[], + "responses":{"200":{"result":"success"}}, + "security":[] + } + }, + "/rolemgmt/role/version": + { + "get": + { + "tags":["rolemgmt"], + "summary":"get rolemgmt role version", + "description":"get rolemgmt role version", + "operationId":"get_rolemgmt_role_version", + "consumes":[], + "produces":["application/json"], + "parameters":[{ + "name":"name", + "in":"query", + "description":"role name", + "required":true, + "type":"string" + }], + "responses":{"200":{"result":"success"}}, + "security":[] + } + }, + "/rolemgmt/roles": + { + "get": + { + "tags":["rolemgmt"], + "summary":"get roles", + "description":"get roles", + "operationId":"get_rolemgmt_roles", + "consumes":[], + "produces":["application/json"], + "parameters":[], + "responses":{ + "200":{"description":"available roles", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Role" + } + }, + "400":{"description":"no roles configured"} + } + }, + "security":[] + } + }, + "/rolemgmt/role/status": + { + "get": + { + "tags":["rolemgmt"], + "summary":"get roles", + "description":"get roles", + "operationId":"get_rolemgmt_roles", + "consumes":[], + "produces":["application/json"], + "parameters":[{ + "name":"name", + "in":"query", + "description":"role name", + "required":true, + "type":"string" + }, + { + "name":"taskid", + "in":"query", + "description":"taskid", + "required":true, + "type":"string" + } + ], + "responses":{ + "200":{"description":{"status":"status"}}, + "400":{"description":"task not found"} + }, + "security":[] + } + }, + "/rolemgmt/role/logs": + { + "get": + { + "tags":["rolemgmt"], + "summary":"get logs", + "description":"get logs", + "operationId":"get_rolemgmt_logs", + "consumes":[], + "produces":["application/json"], + "parameters":[ + { + "name":"taskid", + "in":"query", + "description":"taskid", + "required":true, + "type":"string" + }, + { + "name":"startat", + "in":"query", + "description":"start at", + "required":true, + "type":"integer" + }, + { + "name":"count", + "in":"query", + "description":"count", + "required":true, + "type":"integer" + } + ], + "responses":{ + "200":{"description":{"status":"status"}}, + "400":{"description":"task not found"} + }, + "security":[] + } + }, + "/rolemgmt/role/alter": + { + "put": + { + "tags":["rolemgmt"], + "summary":"enable role", + "description":"enable a role", + "operationId":"role_alter_put", + "consumes":[], + "produces":["application/json"], + "parameters":[{ + "name":"name", + "in":"query", + "description":"role name", + "required":true, + "type":"string" + }, + { + "name":"config", + "in":"body", + "description":"config", + "required":true, + "type":"string" + }], + "responses":{ + "200":{"description":{"taskid":"new task id"}}, + "400":{"description":"alter failed"} + }, + "security":[] + }, + "patch": + { + "tags":["rolemgmt"], + "summary":"update role", + "description":"update a role", + "operationId":"role_alter_patch", + "consumes":[], + "produces":["application/json"], + "parameters":[{ + "name":"name", + "in":"query", + "description":"role name", + "required":true, + "type":"string" + }, + { + "name":"config", + "in":"body", + "description":"config", + "required":false, + "type":"string" + }], + "responses":{ + "200":{"description":{"taskid":"new task id"}}, + "400":{"description":"alter failed"} + }, + "security":[] + }, + "delete": + { + "tags":["rolemgmt"], + "summary":"remove role", + "description":"remove a role", + "operationId":"role_alter_delete", + "consumes":[], + "produces":["application/json"], + "parameters":[{ + "name":"name", + "in":"query", + "description":"role name", + "required":true, + "type":"string" + }, + { + "name":"config", + "in":"body", + "description":"config", + "required":false, + "type":"string" + }], + "responses":{ + "200":{"description":{"taskid":"new task id"}}, + "400":{"description":"alter failed"} + }, + "security":[] + } } }, "securityDefinitions": { @@ -2060,6 +2289,14 @@ "addr_type": {"type": "string"}, "prefix": {"type": "string"} } + }, + "Role": { + "type": "object", + "properties": { + "id": {"type": "string"}, + "name": {"type": "string"}, + "description": {"type": "string"} + } } } } diff --git a/configure.ac b/configure.ac index 83045ca..bd6c195 100644 --- a/configure.ac +++ b/configure.ac @@ -234,6 +234,10 @@ AM_CONDITIONAL([LIBCURL], [test "$have_libcurl" = "yes"]) PKG_CHECK_MODULES([COPENAPI], [copenapi], [have_libcopenapi=yes], [have_libcopenapi=no]) AM_CONDITIONAL([COPENAPI], [test "$have_libcopenapi" = "yes"]) +#uuid +PKG_CHECK_MODULES([UUID], [uuid], [have_libuuid=yes], [have_libuuid=no]) +AM_CONDITIONAL([UUID], [test "$have_libuuid" = "yes"]) + #makefiles AC_CONFIG_FILES([Makefile common/Makefile @@ -244,6 +248,7 @@ AC_CONFIG_FILES([Makefile server/demo/Makefile server/extras/Makefile server/restutils/Makefile + server/rolemgmt/Makefile server/security/Makefile privsep/Makefile privsep/demo/Makefile @@ -257,6 +262,8 @@ AC_CONFIG_FILES([Makefile tools/cli/pkgmgmt/Makefile tools/cli/netmgmt/Makefile tools/cli/usermgmt/Makefile + tools/cli/rolemgmt/Makefile + tools/pmd.spec ]) #pmd conf dir diff --git a/idl/Makefile.am b/idl/Makefile.am index 122548c..0fd0741 100644 --- a/idl/Makefile.am +++ b/idl/Makefile.am @@ -24,6 +24,12 @@ CLEANFILES = \ netmgmt_h.h \ netmgmt_cstub.c \ netmgmt_sstub.c \ + rolemgmt_h.h \ + rolemgmt_cstub.c \ + rolemgmt_sstub.c \ + rpmostree_h.h \ + rpmostree_cstub.c \ + rpmostree_sstub.c \ usermgmt_h.h \ usermgmt_cstub.c \ usermgmt_sstub.c \ @@ -54,7 +60,9 @@ BUILT_SOURCES = demo_h.h \ pkgmgmt_privsep_h.h \ netmgmt_privsep_h.h \ fwmgmt_privsep_h.h \ - usermgmt_privsep_h.h + usermgmt_privsep_h.h \ + rolemgmt_h.h \ + rpmostree_h.h demo_h.h demo_cstub.c: $(idl_srcdir)/demo.idl $(DCEIDL) $(IDLFLAGS) -keep c_source -header demo_h.h -I$(idl_srcdir) $< @@ -68,6 +76,10 @@ pmd_h.h pmd_cstub.c: $(idl_srcdir)/pmd.idl $(DCEIDL) $(IDLFLAGS) -keep c_source -header pmd_h.h -I$(idl_srcdir) $< netmgmt_h.h netmgmt_cstub.c: $(idl_srcdir)/netmgmt.idl $(DCEIDL) $(IDLFLAGS) -keep c_source -header netmgmt_h.h -I$(idl_srcdir) $< +rolemgmt_h.h rolemgmt_cstub.c: $(idl_srcdir)/rolemgmt.idl + $(DCEIDL) $(IDLFLAGS) -keep c_source -header rolemgmt_h.h -I$(idl_srcdir) $< +rpmostree_h.h rpmostree_cstub.c: $(idl_srcdir)/rpmostree.idl + $(DCEIDL) $(IDLFLAGS) -keep c_source -header rpmostree_h.h -I$(idl_srcdir) $< usermgmt_h.h usermgmt_cstub.c: $(idl_srcdir)/usermgmt.idl $(DCEIDL) $(IDLFLAGS) -keep c_source -header usermgmt_h.h -I$(idl_srcdir) $< diff --git a/idl/rolemgmt.idl b/idl/rolemgmt.idl index 43dbde3..fc4e6e6 100644 --- a/idl/rolemgmt.idl +++ b/idl/rolemgmt.idl @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - [ uuid (5775ec92-176c-414c-b40d-e24b00904ff7), version(1.0), @@ -36,4 +35,45 @@ interface rolemgmt [in] handle_t hBinding, [out] PPMD_RPC_ROLEMGMT_ROLE_ARRAY *ppRoleArray ); + + unsigned32 + rolemgmt_rpc_role_version( + [in] handle_t hBinding, + [in] wstring_t pwszName, + [out] wstring_t* ppwszVersion + ); + + unsigned32 + rolemgmt_rpc_role_get_status( + [in] handle_t hBinding, + [in] wstring_t pwszName, + [in] wstring_t pwszTaskUUID, + [out] RPC_ROLE_STATUS *pnStatus + ); + + unsigned32 + rolemgmt_rpc_role_get_prereqs( + [in] handle_t hBinding, + [in] wstring_t pwszName, + [in] RPC_ROLE_OPERATION nOperation, + [out] PPMD_RPC_ROLEMGMT_PREREQ_ARRAY *ppPrereqArray + ); + + unsigned32 + rolemgmt_rpc_role_alter( + [in] handle_t hBinding, + [in] wstring_t pwszName, + [in] RPC_ROLE_OPERATION nOperation, + [in] wstring_t pwszConfigJson, + [out] wstring_t *pszTaskUUID + ); + + unsigned32 + rolemgmt_rpc_role_get_log( + [in] handle_t hBinding, + [in] wstring_t pwszTaskUUID, + [in] unsigned32 nOffset, + [in] unsigned32 nEntriesToFetch, + [out] PPMD_RPC_ROLEMGMT_TASK_LOG_ARRAY *ppTaskLogArray + ); } diff --git a/idl/rolemgmtrpctypes.h b/idl/rolemgmtrpctypes.h index 1d5a25d..80c37f3 100644 --- a/idl/rolemgmtrpctypes.h +++ b/idl/rolemgmtrpctypes.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #ifndef __ROLEMGMT_RPC_TYPES_H__ #define __ROLEMGMT_RPC_TYPES_H__ @@ -31,9 +30,36 @@ cpp_quote("#if 0") #endif +typedef enum +{ + RPC_ROLE_STATE_IDLE, + RPC_ROLE_STATE_ALTER, + RPC_ROLE_STATE_PREREQ +}RPC_ROLE_STATE; + +typedef enum +{ + RPC_ROLE_OPERATION_NONE, + RPC_ROLE_OPERATION_ENABLE, + RPC_ROLE_OPERATION_UPDATE, + RPC_ROLE_OPERATION_REMOVE +}RPC_ROLE_OPERATION; + +typedef enum +{ + RPC_ROLE_STATUS_NONE, + RPC_ROLE_STATUS_SUCCESS, + RPC_ROLE_STATUS_FAILURE, + RPC_ROLE_STATUS_NOT_STARTED, + RPC_ROLE_STATUS_IN_PROGRESS +}RPC_ROLE_STATUS; + typedef struct _PMD_RPC_ROLEMGMT_ROLE_ { - wstring_t pwszRole; + wstring_t pwszId; + wstring_t pwszName; + wstring_t pwszDisplayName; + wstring_t pwszDescription; }PMD_RPC_ROLEMGMT_ROLE, *PPMD_RPC_ROLEMGMT_ROLE; typedef struct _PMD_RPC_ROLEMGMT_ROLE_ARRAY_ @@ -45,6 +71,44 @@ typedef struct _PMD_RPC_ROLEMGMT_ROLE_ARRAY_ PPMD_RPC_ROLEMGMT_ROLE pRoles; }PMD_RPC_ROLEMGMT_ROLE_ARRAY, *PPMD_RPC_ROLEMGMT_ROLE_ARRAY; +typedef struct _PMD_RPC_ROLEMGMT_PREREQ_ +{ + wstring_t pwszName; + wstring_t pwszDescription; +}PMD_RPC_ROLEMGMT_PREREQ, *PPMD_RPC_ROLEMGMT_PREREQ; + +typedef struct _PMD_RPC_ROLEMGMT_STATUS_ +{ + RPC_ROLE_STATE nState; + unsigned32 nSecondsElapsed; + unsigned32 nPercentCompleted; + wstring_t pwszStatus; +}PMD_RPC_ROLEMGMT_STATUS, *PPMD_RPC_ROLEMGMT_STATUS; + +typedef struct _PMD_RPC_ROLEMGMT_PREREQ_ARRAY_ +{ + unsigned32 dwCount; +#ifdef _DCE_IDL_ + [size_is(dwCount)] +#endif + PPMD_RPC_ROLEMGMT_PREREQ pPrereqs; +}PMD_RPC_ROLEMGMT_PREREQ_ARRAY, *PPMD_RPC_ROLEMGMT_PREREQ_ARRAY; + +typedef struct _PMD_RPC_ROLEMGMT_TASK_LOG_ +{ + unsigned long int tStamp; + wstring_t pwszLog; +}PMD_RPC_ROLEMGMT_TASK_LOG, *PPMD_RPC_ROLEMGMT_TASK_LOG; + +typedef struct _PMD_RPC_ROLEMGMT_TASK_LOG_ARRAY_ +{ + unsigned32 dwCount; +#ifdef _DCE_IDL_ + [size_is(dwCount)] +#endif + PPMD_RPC_ROLEMGMT_TASK_LOG pTaskLogs; +}PMD_RPC_ROLEMGMT_TASK_LOG_ARRAY, *PPMD_RPC_ROLEMGMT_TASK_LOG_ARRAY; + #ifdef _DCE_IDL_ cpp_quote("#endif") #endif diff --git a/idl/rpmostree.idl b/idl/rpmostree.idl new file mode 100644 index 0000000..4ef6a73 --- /dev/null +++ b/idl/rpmostree.idl @@ -0,0 +1,51 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + + +[ + uuid (e8e49806-5a88-11e6-8a22-000c297d36e2), + version(1.0), + pointer_default(unique) +] + +interface rpmostree +{ +#include +#include "pmdrpctypes.h" +#include "rpmostreerpctypes.h" + + unsigned32 + rpmostree_rpc_version( + [in] handle_t hBinding, + [out] wstring_t* ppwszVersion + ); + + unsigned32 + rpmostree_rpc_server_info( + [in] handle_t hBinding, + [out] PPMD_RPMOSTREE_SERVER_INFO* ppInfo + ); + + unsigned32 + rpmostree_rpc_client_info( + [in] handle_t hBinding, + [out] PPMD_RPMOSTREE_CLIENT_INFO* ppInfo + ); + + unsigned32 + rpmostree_rpc_client_syncto( + [in] handle_t hBinding, + [in] wstring_t pwszHash + ); +} diff --git a/idl/rpmostreerpctypes.h b/idl/rpmostreerpctypes.h new file mode 100644 index 0000000..caefa97 --- /dev/null +++ b/idl/rpmostreerpctypes.h @@ -0,0 +1,57 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + + +#ifndef __RPMOSTREE_RPC_TYPES_H__ +#define __RPMOSTREE_RPC_TYPES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#if (!defined NO_LIKEWISE && !defined _WIN32) +#include +#endif + +#ifdef _DCE_IDL_ + +cpp_quote("#include ") +cpp_quote("#if 0") + +#endif + +typedef struct _PMD_RPMOSTREE_SERVER_INFO_ +{ + unsigned32 dwServerType; + wstring_t pwszServerUrl; + wstring_t pwszCurrentHash; +}PMD_RPMOSTREE_SERVER_INFO, *PPMD_RPMOSTREE_SERVER_INFO; + +typedef struct _PMD_RPMOSTREE_CLIENT_INFO_ +{ + unsigned32 dwServerType; + wstring_t pwszComposeServer; + wstring_t pwszCurrentHash; + wstring_t pwszLastSyncDate; +}PMD_RPMOSTREE_CLIENT_INFO, *PPMD_RPMOSTREE_CLIENT_INFO; + +#ifdef _DCE_IDL_ +cpp_quote("#endif") +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __RPMOSTREE_RPC_TYPES_H__ */ diff --git a/include/pmd_rolemgmt.h b/include/pmd_rolemgmt.h index f553031..5482be0 100644 --- a/include/pmd_rolemgmt.h +++ b/include/pmd_rolemgmt.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #pragma once #ifdef __cplusplus @@ -21,6 +20,7 @@ extern "C" { #include "pmdtypes.h" #include "pmd_rolemgmt_types.h" +#include "roleplugin.h" uint32_t rolemgmt_get_version( @@ -34,6 +34,49 @@ rolemgmt_get_roles( PPMD_ROLEMGMT_ROLE *ppRoles ); +uint32_t +rolemgmt_get_role_version( + PPMDHANDLE hHandle, + const char *pszName, + char **ppszVersion + ); + +uint32_t +rolemgmt_get_prereqs( + PPMDHANDLE hHandle, + const char *pszName, + PMD_ROLE_OPERATION nOperation, + PPMD_ROLE_PREREQ *ppPrereqs, + uint32_t *pdwPrereqCount + ); + +uint32_t +rolemgmt_alter( + PPMDHANDLE hHandle, + const char *pszName, + int nOperation, + const char *pszConfigJson, + char **ppszTaskUUID + ); + +uint32_t +rolemgmt_get_status( + PPMDHANDLE hHandle, + const char *pszName, + const char *pszTaskUUID, + PMD_ROLE_STATUS *pnStatus + ); + +uint32_t +rolemgmt_get_log( + PPMDHANDLE hHandle, + const char *pszTaskUUID, + uint32_t dwOffset, + uint32_t dwEntriesToFetch, + PPMD_ROLEMGMT_TASK_LOG *ppTaskLogs, + uint32_t *pdwTaskLogCount + ); + void rolemgmt_free_roles( PPMD_ROLEMGMT_ROLE pRoles diff --git a/include/pmd_rolemgmt_types.h b/include/pmd_rolemgmt_types.h index 67b997d..31a1ae1 100644 --- a/include/pmd_rolemgmt_types.h +++ b/include/pmd_rolemgmt_types.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #pragma once #ifdef __cplusplus @@ -22,9 +21,24 @@ extern "C" { typedef struct _PMD_ROLEMGMT_ROLE_ { char *pszRole; + char *pszId; + char *pszName; + char *pszDisplayName; + char *pszDescription; + char *pszParent; + char *pszPlugin; + int nChildCount; + struct _PMD_ROLEMGMT_ROLE_ *pParent; + struct _PMD_ROLEMGMT_ROLE_ **ppChildren; struct _PMD_ROLEMGMT_ROLE_ *pNext; }PMD_ROLEMGMT_ROLE, *PPMD_ROLEMGMT_ROLE; +typedef struct _PMD_ROLEMGMT_TASK_LOG_ +{ + time_t tStamp; + char *pszLog; +}PMD_ROLEMGMT_TASK_LOG, *PPMD_ROLEMGMT_TASK_LOG; + #ifdef __cplusplus } #endif diff --git a/include/pmderror.h b/include/pmderror.h index 55dc8f3..95356d7 100644 --- a/include/pmderror.h +++ b/include/pmderror.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #pragma once #ifdef __cplusplus @@ -20,22 +19,37 @@ extern "C" { #endif //PMD specific errors(3000 to 3999) -#define ERROR_PMD_BASE 3000 -#define ERROR_PMD_FAIL (ERROR_PMD_BASE + 1) -#define ERROR_PMD_CONF_FILE_LOAD (ERROR_PMD_BASE + 2) -#define ERROR_PMD_BASE64_ENCODE (ERROR_PMD_BASE + 3) -#define ERROR_PMD_BASE64_DECODE (ERROR_PMD_BASE + 4) -#define ERROR_PMD_USER_PASS_FORMAT (ERROR_PMD_BASE + 5) -#define ERROR_PMD_JSON_SET_VALUE (ERROR_PMD_BASE + 6) +#define ERROR_PMD_BASE 3000 +#define ERROR_PMD_FAIL (ERROR_PMD_BASE + 1) +#define ERROR_PMD_NOTHING_TO_DO (ERROR_PMD_BASE + 2) +#define ERROR_PMD_CONF_FILE_LOAD (ERROR_PMD_BASE + 3) +#define ERROR_PMD_BASE64_ENCODE (ERROR_PMD_BASE + 4) +#define ERROR_PMD_BASE64_DECODE (ERROR_PMD_BASE + 5) +#define ERROR_PMD_USER_PASS_FORMAT (ERROR_PMD_BASE + 6) +#define ERROR_PMD_JSON_SET_VALUE (ERROR_PMD_BASE + 7) +#define ERROR_PMD_ROLES_DIR_OPEN (ERROR_PMD_BASE + 21) +#define ERROR_PMD_ROLES_NO_SUCH_ROLE (ERROR_PMD_BASE + 22) +#define ERROR_PMD_ROLES_PLUGIN_NOT_SET (ERROR_PMD_BASE + 23) +#define ERROR_PMD_ROLE_CONFIG_NO_PARENT (ERROR_PMD_BASE + 24) +#define ERROR_PMD_ROLE_UNMAPPED_FN (ERROR_PMD_BASE + 25) +#define ERROR_PMD_ROLE_UNMAPPED_LOAD (ERROR_PMD_BASE + 26) +#define ERROR_PMD_ROLE_PLUGIN_BAD (ERROR_PMD_BASE + 27) +#define ERROR_PMD_ROLE_PLUGIN_DISABLED (ERROR_PMD_BASE + 28) +#define ERROR_PMD_ROLE_PLUGIN_HAS_TASKS (ERROR_PMD_BASE + 29) +#define ERROR_PMD_ROLE_TASK_NOT_FOUND (ERROR_PMD_BASE + 30) +#define ERROR_PMD_ROLE_TASK_NO_LOGS (ERROR_PMD_BASE + 31) +#define ERROR_PMD_ROLE_PATH_MISMATCH (ERROR_PMD_BASE + 32) +#define ERROR_PMD_ROLE_BAD_STATUS (ERROR_PMD_BASE + 33) +#define ERROR_PMD_ROLE_BAD_OPERATION (ERROR_PMD_BASE + 34) //REST specific errors (3500 to 3600) -#define ERROR_PMD_REST_BASE 3600 +#define ERROR_PMD_REST_BASE 3500 #define ERROR_PMD_REST_AUTH_REQUIRED (ERROR_PMD_REST_BASE + 1) #define ERROR_PMD_REST_AUTH_BASIC_MIN (ERROR_PMD_REST_BASE + 2) #define ERROR_INVALID_REST_AUTH (ERROR_PMD_REST_BASE + 3) //System errors 3600 and up -#define ERROR_PMD_SYSTEM_BASE 3600 +#define ERROR_PMD_SYSTEM_BASE 3600 // No search results found #define ERROR_PMD_NO_SEARCH_RESULTS 3601 #define ERROR_PMD_INVALID_PARAMETER (ERROR_PMD_SYSTEM_BASE + EINVAL) @@ -56,11 +70,13 @@ extern "C" { #define ERROR_PMD_IS_DAEMON_USER_GROUP ERROR_PMD_SYSTEM_BASE + 136 #define ERROR_PMD_INVALID_CMD ERROR_PMD_SYSTEM_BASE + 137 #define ERROR_PMD_CMD_UNEXPECTED_EXIT ERROR_PMD_SYSTEM_BASE + 138 +#define ERROR_PMD_LIBACC (ERROR_PMD_SYSTEM_BASE + ELIBACC) +#define ERROR_PMD_ALREADY (ERROR_PMD_SYSTEM_BASE + EALREADY) //pkgmgmt errors 4000 and up -#define ERROR_PMD_PKG_BASE 4000 -#define ERROR_PMD_MISSING_PKG_ARGS (ERROR_PMD_PKG_BASE + 1) -#define ERROR_PMD_ALTER_MODE_INVALID (ERROR_PMD_PKG_BASE + 2) +#define ERROR_PMD_PKG_BASE 4000 +#define ERROR_PMD_MISSING_PKG_ARGS (ERROR_PMD_PKG_BASE + 1) +#define ERROR_PMD_ALTER_MODE_INVALID (ERROR_PMD_PKG_BASE + 2) //netmgmt errors 4096 and up #define ERROR_PMD_NET_BASE 4096 @@ -68,6 +84,9 @@ extern "C" { //netmgmt errors 4300 and up #define ERROR_PMD_USR_BASE 4300 +//usermgmt errors 4100 and up +#define ERROR_PMD_USER_BASE 4100 + #ifdef __cplusplus } #endif diff --git a/include/roleplugin.h b/include/roleplugin.h new file mode 100644 index 0000000..4c6aed5 --- /dev/null +++ b/include/roleplugin.h @@ -0,0 +1,136 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +#pragma once + +#include //for uint32_t + +#define PMD_ROLE_PLUGIN_VERSION_MAJOR "0" +#define PMD_ROLE_PLUGIN_VERSION_MINOR "0" +#define PMD_ROLE_PLUGIN_VERSION_RELEASE "1" + +typedef struct _PMD_ROLE_HANDLE_ *PPMD_ROLE_HANDLE; + +typedef enum +{ + ROLE_OPERATION_NONE, + ROLE_OPERATION_ENABLE, + ROLE_OPERATION_UPDATE, + ROLE_OPERATION_REMOVE, + ROLE_OPERATION_MAX +}PMD_ROLE_OPERATION; + +typedef enum +{ + ROLE_STATUS_NONE, + ROLE_STATUS_SUCCESS, + ROLE_STATUS_FAILURE, + ROLE_STATUS_NOT_STARTED, + ROLE_STATUS_IN_PROGRESS +}PMD_ROLE_STATUS; + +typedef struct _PMD_ROLE_PREREQ_ +{ + char *pszName; + char *pszDescription; +}PMD_ROLE_PREREQ, *PPMD_ROLE_PREREQ; + +typedef struct _PMD_ROLE_ERROR_ +{ + uint32_t dwError; //Error code + char *pszError; //Error string + char *pszSuggestions; //Suggestions to recover +}PMD_ROLE_ERROR, *PPMD_ROLE_ERROR; + +typedef struct _PMD_ROLE_STATUS_DATA_ +{ + int nInstalled; + int nConfigured; +}PMD_ROLE_STATUS_DATA, *PPMD_ROLE_STATUS_DATA; + +//status callback +typedef +uint32_t +(*PFN_ALTER_PROGRESS_CALLBACK)( + const char *pszTaskUUID, + const char *pszProgress + ); + +//Function pointer defs + +//version +typedef uint32_t +(*PFN_PMD_ROLE_VERSION)( + char **ppszVersion + ); + +//open to get a handle for operations. +typedef uint32_t +(*PFN_PMD_ROLE_OPEN)( + PPMD_ROLE_HANDLE *ppHandle + ); + +//close role operations +typedef uint32_t +(*PFN_PMD_ROLE_CLOSE)( + PPMD_ROLE_HANDLE pHandle + ); + +//return installed status, configured status +typedef uint32_t +(*PFN_PMD_ROLE_GET_STATUS)( + PPMD_ROLE_HANDLE pHandle, + PPMD_ROLE_STATUS_DATA *ppStatusData + ); + +//get list of pre-requisites +typedef uint32_t +(*PFN_PMD_ROLE_GET_PREREQS)( + PPMD_ROLE_HANDLE pHandle, + PMD_ROLE_OPERATION nOperation, + PPMD_ROLE_PREREQ *ppPreReqs, + uint32_t *pdwPreReqCount + ); + +//perform role alter operation +typedef uint32_t +(*PFN_PMD_ROLE_ALTER)( + PPMD_ROLE_HANDLE pHandle, + PMD_ROLE_OPERATION nOperation, + const char *pszConfigJson, + const char *pszTaskID, + PFN_ALTER_PROGRESS_CALLBACK pFnCallback, + PPMD_ROLE_ERROR *ppError + ); + +typedef struct _PMD_ROLE_PLUGIN_INTERFACE_ +{ + PFN_PMD_ROLE_VERSION pFnRoleVersion; + PFN_PMD_ROLE_OPEN pFnRoleOpen; + PFN_PMD_ROLE_CLOSE pFnRoleClose; + PFN_PMD_ROLE_GET_STATUS pFnRoleGetStatus; + PFN_PMD_ROLE_GET_PREREQS pFnRoleGetPreReqs; + PFN_PMD_ROLE_ALTER pFnRoleAlter; +}PMD_ROLE_PLUGIN_INTERFACE, *PPMD_ROLE_PLUGIN_INTERFACE; + +//Entry point for plugins +uint32_t +pmd_roleplugin_load_interface( + PPMD_ROLE_PLUGIN_INTERFACE *ppInterface + ); + +//Entry point for plugins +uint32_t +pmd_roleplugin_unload_interface( + PPMD_ROLE_PLUGIN_INTERFACE pInterface + ); diff --git a/pmd.spec.in b/pmd.spec.in index 95e4854..cb8fc19 100644 --- a/pmd.spec.in +++ b/pmd.spec.in @@ -5,7 +5,7 @@ Summary: Photon Management Daemon Name: pmd Version: @VERSION@ -Release: 1%{?dist} +Release: 2%{?dist} License: Apache 2.0 URL: https://www.github.com/vmware/pmd Group: Applications/System @@ -121,6 +121,8 @@ install -D -m 444 conf/api_sddl.conf %{buildroot}/etc/pmd/api_sddl.conf install -D -m 444 conf/restconfig.txt %{buildroot}/etc/pmd/restconfig.txt install -d -m 0755 %{buildroot}/usr/lib/tmpfiles.d/ install -m 0644 conf/pmd-tmpfiles.conf %{buildroot}/usr/lib/tmpfiles.d/%{name}.conf +install -d -m 0755 %{buildroot}/etc/pmd.roles.d/ +install -d -m 0755 %{buildroot}/etc/pmd.roles.plugins.d/ # Pre-install %pre @@ -277,6 +279,8 @@ rm -rf %{buildroot}/* /etc/pmd/restapispec.json /etc/pmd/restconfig.txt %attr(0766, %{name}, %{name}) %dir /var/log/%{name} + %dir /etc/pmd.roles.plugins.d/ + %dir /etc/pmd.roles.d/ %_tmpfilesdir/%{name}.conf %files libs @@ -298,5 +302,7 @@ rm -rf %{buildroot}/* %{_python3_sitearch}/%{name}_python-*.egg-info %changelog +* Thu Jul 18 2019 Tapas Kundu 0.1-2 +- Updated the spec for including role mgmt changes. * Thu May 04 2017 Priyesh Padmavilasom 0.1-1 - Initial build. First version diff --git a/privsep/global.c b/privsep/global.c index 0722519..dcffd97 100644 --- a/privsep/global.c +++ b/privsep/global.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" PPRIVSEP_SERVER_ENV gpServerEnv = NULL; diff --git a/python/Makefile.am b/python/Makefile.am index 863799f..4fa407a 100644 --- a/python/Makefile.am +++ b/python/Makefile.am @@ -20,6 +20,10 @@ _pmd_la_SOURCES = \ pkgmgmt_solvedinfo_py.c \ pkgmgmt_utils.c \ pmdmodule.c \ + rolemgmt_py.c \ + rolemgmt_prereq_py.c \ + rolemgmt_role_py.c \ + rolemgmt_logentry_py.c \ server_py.c \ utils.c diff --git a/python/includes.h b/python/includes.h index fccc8ad..1977679 100644 --- a/python/includes.h +++ b/python/includes.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -15,10 +15,12 @@ #pragma once #include +#include #include #include #include #include +#include #include #include "../common/defines.h" #include "../common/structs.h" @@ -29,6 +31,10 @@ #include "fwmgmt_py.h" #include "netmgmt_py.h" #include "pkgmgmt_py.h" +#include "rolemgmt_py.h" +#include "rolemgmt_prereq_py.h" +#include "rolemgmt_role_py.h" +#include "rolemgmt_logentry_py.h" #include "netmgmt_link_py.h" #include "netmgmt_route_py.h" #include "netmgmt_system_py.h" diff --git a/python/pmdmodule.c b/python/pmdmodule.c index 55b8e95..7636a72 100644 --- a/python/pmdmodule.c +++ b/python/pmdmodule.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" static char pmd__doc__[] = ""; @@ -31,6 +30,10 @@ prepareInitModule( if (PyType_Ready(&repodataType) < 0) return 0; if (PyType_Ready(&packageType) < 0) return 0; if (PyType_Ready(&solvedInfoType) < 0) return 0; + if (PyType_Ready(&rolemgmtType) < 0) return 0; + if (PyType_Ready(&rolemgmt_roleType) < 0) return 0; + if (PyType_Ready(&rolemgmt_prereqType) < 0) return 0; + if (PyType_Ready(&rolemgmt_logentryType) < 0) return 0; return 1; } diff --git a/python/prototypes.h b/python/prototypes.h index 3852b6e..2036802 100644 --- a/python/prototypes.h +++ b/python/prototypes.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #pragma once //pkgmgmt_utils.c uint32_t @@ -58,6 +57,11 @@ string_from_py_string( PyObject *pyString ); +void +raise_exception( + uint32_t dwErrorCode + ); + //pkgmgmt_repodata.c uint32_t py_make_repodata( @@ -78,3 +82,24 @@ py_make_solvedinfo( PTDNF_SOLVED_PKG_INFO pSolvedInfo, PyObject **ppPySolvedInfo ); + +//rolemgmt_role_py.c +uint32_t +rolemgmt_role_py_make( + PPMD_ROLEMGMT_ROLE pRole, + PyObject **ppPyRole + ); + +//rolemgmt_prereq_py.c +uint32_t +rolemgmt_prereq_py_make( + PPMD_ROLE_PREREQ pPrereq, + PPY_ROLEMGMT_PREREQ *ppPyPrereq + ); + +//rolemgmt_logentry_py.c +uint32_t +rolemgmt_logentry_py_make( + PPMD_ROLEMGMT_TASK_LOG pLogEntry, + PPY_ROLEMGMT_LOG_ENTRY *ppPyLogEntry + ); diff --git a/python/rolemgmt_logentry_py.c b/python/rolemgmt_logentry_py.c new file mode 100644 index 0000000..c1f2b85 --- /dev/null +++ b/python/rolemgmt_logentry_py.c @@ -0,0 +1,240 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#include "includes.h" + +char rolemgmt_logentry__doc__[] = ""; + +void +rolemgmt_logentry_dealloc(PY_ROLEMGMT_LOG_ENTRY *self) +{ + Py_XDECREF(self->log); + Py_TYPE(self)->tp_free((PyObject*)self); +} + +PyObject * +rolemgmt_logentry_new( + PyTypeObject *type, + PyObject *args, + PyObject *kwds) +{ + uint32_t dwError = 0; + PPY_ROLEMGMT_LOG_ENTRY self = NULL; + + self = (PPY_ROLEMGMT_LOG_ENTRY)type->tp_alloc(type, 0); + if (self != NULL) + { + self->tStamp = 0; + if(!(self->log = PyBytes_FromString(""))) + { + dwError = ERROR_PMD_OUT_OF_MEMORY; + BAIL_ON_PMD_ERROR(dwError); + } + } + +cleanup: + return (PyObject *)self; + +error: + Py_DECREF(self); + self = NULL; + goto cleanup; +} + +int +rolemgmt_logentry_init( + PY_ROLEMGMT_LOG_ENTRY *self, + PyObject *args, + PyObject *kwds + ) +{ + uint32_t dwError = 0; + long tStamp = 0; + PyObject *log = NULL; + PyObject *tmp = NULL; + + static char *kwlist[] = {"tstamp", "log", NULL}; + + if (!PyArg_ParseTupleAndKeywords( + args, kwds, "|iS", kwlist, + &tStamp, &log)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if (log) + { + tmp = self->log; + Py_INCREF(log); + self->log = log; + Py_XDECREF(tmp); + } + +cleanup: + return dwError > 0 ? -1 : 0; + +error: + fprintf(stderr, "Error = %d\n", dwError); + goto cleanup; +} + +PyObject* +rolemgmt_logentry_repr( + PyObject *self + ) +{ + uint32_t dwError = 0; + PyObject *pyRepr = Py_None; + PPY_ROLEMGMT_LOG_ENTRY pLogEntry = NULL; + char *pszRepr = NULL; + + pLogEntry = (PPY_ROLEMGMT_LOG_ENTRY)self; + dwError = PMDAllocateStringPrintf( + &pszRepr, + "{tstamp: %ld, log: %s}", + pLogEntry->tStamp, + pLogEntry->log ? PyBytes_AsString(pLogEntry->log) : ""); + BAIL_ON_PMD_ERROR(dwError); + + pyRepr = Py_BuildValue("s", pszRepr); + Py_INCREF(pyRepr); + +cleanup: + PMD_SAFE_FREE_MEMORY(pszRepr); + return pyRepr; + +error: + pyRepr = NULL; + goto cleanup; +} + +PyObject* +rolemgmt_logentry_str( + PyObject *self + ) +{ + return rolemgmt_logentry_repr(self); +} + +uint32_t +rolemgmt_logentry_py_make( + PPMD_ROLEMGMT_TASK_LOG pLogEntry, + PPY_ROLEMGMT_LOG_ENTRY *ppPyLogEntry + ) +{ + uint32_t dwError = 0; + PPY_ROLEMGMT_LOG_ENTRY pPyLogEntry = NULL; + PyTypeObject *retType = &rolemgmt_logentryType; + struct tm *pTime = NULL; + + if(!pLogEntry || !ppPyLogEntry) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + pPyLogEntry = (PPY_ROLEMGMT_LOG_ENTRY)retType->tp_alloc(retType, 0); + if(!pPyLogEntry) + { + dwError = ERROR_PMD_OUT_OF_MEMORY; + BAIL_ON_PMD_ERROR(dwError); + } + + pTime = gmtime(&pLogEntry->tStamp); + if(!pTime) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + +printf("before time:%d:%d:%d\n", pTime->tm_hour, pTime->tm_min, pTime->tm_sec); +/* + pPyLogEntry->tstamp = PyTime_FromTime( + 0, + 0, + 0, + 0); +*/ +printf("after time\n"); + pPyLogEntry->log = PyBytes_FromString(pLogEntry->pszLog); + + *ppPyLogEntry = pPyLogEntry; +cleanup: + return dwError; + +error: + Py_XDECREF(pPyLogEntry); + pPyLogEntry = NULL; + goto cleanup; +} + +static PyGetSetDef rolemgmt_logentry_getset[] = { + {NULL} /* Sentinel */ +}; + +static PyMethodDef rolemgmt_logentry_methods[] = { + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +static PyMemberDef rolemgmt_logentry_members[] = { + {"tStamp", T_OBJECT_EX, offsetof(PY_ROLEMGMT_LOG_ENTRY, tStamp), 0, + "log date time"}, + {"log", T_OBJECT_EX, offsetof(PY_ROLEMGMT_LOG_ENTRY, log), 0, + "log data"}, + {NULL} /* Sentinel */ +}; + +PyTypeObject rolemgmt_logentryType = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rolemgmt_logentry", /*tp_name*/ + sizeof(PY_ROLEMGMT_LOG_ENTRY), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)rolemgmt_logentry_dealloc,/*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + rolemgmt_logentry_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + rolemgmt_logentry_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + rolemgmt_logentry__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + rolemgmt_logentry_methods, /* tp_methods */ + rolemgmt_logentry_members, /* tp_members */ + rolemgmt_logentry_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)rolemgmt_logentry_init, /* tp_init */ + 0, /* tp_alloc */ + rolemgmt_logentry_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; diff --git a/python/rolemgmt_logentry_py.h b/python/rolemgmt_logentry_py.h new file mode 100644 index 0000000..17714b5 --- /dev/null +++ b/python/rolemgmt_logentry_py.h @@ -0,0 +1,17 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#pragma once + +extern PyTypeObject rolemgmt_logentryType; diff --git a/python/rolemgmt_prereq_py.c b/python/rolemgmt_prereq_py.c new file mode 100644 index 0000000..b26dbf0 --- /dev/null +++ b/python/rolemgmt_prereq_py.c @@ -0,0 +1,236 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#include "includes.h" + +char rolemgmt_prereq__doc__[] = ""; + +void +rolemgmt_prereq_dealloc(PY_ROLEMGMT_PREREQ *self) +{ + Py_XDECREF(self->name); + Py_XDECREF(self->description); + Py_TYPE(self)->tp_free((PyObject*)self); +} + +PyObject * +rolemgmt_prereq_new( + PyTypeObject *type, + PyObject *args, + PyObject *kwds) +{ + uint32_t dwError = 0; + PPY_ROLEMGMT_PREREQ self = NULL; + + self = (PPY_ROLEMGMT_PREREQ)type->tp_alloc(type, 0); + if (self != NULL) + { + if(!(self->name = PyBytes_FromString(""))) + { + dwError = ERROR_PMD_OUT_OF_MEMORY; + BAIL_ON_PMD_ERROR(dwError); + } + if(!(self->description = PyBytes_FromString(""))) + { + dwError = ERROR_PMD_OUT_OF_MEMORY; + BAIL_ON_PMD_ERROR(dwError); + } + } + +cleanup: + return (PyObject *)self; + +error: + Py_DECREF(self); + self = NULL; + goto cleanup; +} + +int +rolemgmt_prereq_init( + PY_ROLEMGMT_PREREQ *self, + PyObject *args, + PyObject *kwds + ) +{ + uint32_t dwError = 0; + PyObject *name = NULL; + PyObject *description = NULL; + PyObject *tmp = NULL; + + static char *kwlist[] = {"name", "description", NULL}; + + if (!PyArg_ParseTupleAndKeywords( + args, kwds, "|SS", kwlist, + &name, &description)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if (name) + { + tmp = self->name; + Py_INCREF(name); + self->name = name; + Py_XDECREF(tmp); + } + if (description) + { + tmp = self->description; + Py_INCREF(description); + self->description = description; + Py_XDECREF(tmp); + } + +cleanup: + return dwError > 0 ? -1 : 0; + +error: + fprintf(stderr, "Error = %d\n", dwError); + goto cleanup; +} + +PyObject* +rolemgmt_prereq_repr( + PyObject *self + ) +{ + uint32_t dwError = 0; + PyObject *pyRepr = Py_None; + PPY_ROLEMGMT_PREREQ pPrereq = NULL; + char *pszRepr = NULL; + + pPrereq = (PPY_ROLEMGMT_PREREQ)self; + dwError = PMDAllocateStringPrintf( + &pszRepr, + "{name: %s, description: %s}", + pPrereq->name ? PyBytes_AsString(pPrereq->name) : "", + pPrereq->description ? PyBytes_AsString(pPrereq->description) : ""); + BAIL_ON_PMD_ERROR(dwError); + + pyRepr = Py_BuildValue("s", pszRepr); + Py_INCREF(pyRepr); + +cleanup: + PMD_SAFE_FREE_MEMORY(pszRepr); + return pyRepr; + +error: + pyRepr = NULL; + goto cleanup; +} + +PyObject* +rolemgmt_prereq_str( + PyObject *self + ) +{ + return rolemgmt_prereq_repr(self); +} + +uint32_t +rolemgmt_prereq_py_make( + PPMD_ROLE_PREREQ pPrereq, + PPY_ROLEMGMT_PREREQ *ppPyPrereq + ) +{ + uint32_t dwError = 0; + PPY_ROLEMGMT_PREREQ pPyPrereq = NULL; + PyTypeObject *retType = &rolemgmt_prereqType; + + if(!pPrereq || !ppPyPrereq) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + pPyPrereq = (PPY_ROLEMGMT_PREREQ)retType->tp_alloc(retType, 0); + if(!pPyPrereq) + { + dwError = ERROR_PMD_OUT_OF_MEMORY; + BAIL_ON_PMD_ERROR(dwError); + } + + pPyPrereq->name = PyBytes_FromString(pPrereq->pszName); + pPyPrereq->description = PyBytes_FromString(pPrereq->pszDescription); + + *ppPyPrereq = pPyPrereq; +cleanup: + return dwError; + +error: + Py_XDECREF(pPyPrereq); + pPyPrereq = NULL; + goto cleanup; +} + +static PyGetSetDef rolemgmt_prereq_getset[] = { + {NULL} /* Sentinel */ +}; + +static PyMethodDef rolemgmt_prereq_methods[] = { + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +static PyMemberDef rolemgmt_prereq_members[] = { + {"name", T_OBJECT_EX, offsetof(PY_ROLEMGMT_PREREQ, name), 0, + "role name"}, + {"description", T_OBJECT_EX, offsetof(PY_ROLEMGMT_PREREQ, description), 0, + "role description"}, + {NULL} /* Sentinel */ +}; + +PyTypeObject rolemgmt_prereqType = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rolemgmt_prereq", /*tp_name*/ + sizeof(PY_ROLEMGMT_PREREQ), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)rolemgmt_prereq_dealloc,/*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + rolemgmt_prereq_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + rolemgmt_prereq_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + rolemgmt_prereq__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + rolemgmt_prereq_methods, /* tp_methods */ + rolemgmt_prereq_members, /* tp_members */ + rolemgmt_prereq_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)rolemgmt_prereq_init, /* tp_init */ + 0, /* tp_alloc */ + rolemgmt_prereq_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; diff --git a/python/rolemgmt_prereq_py.h b/python/rolemgmt_prereq_py.h new file mode 100644 index 0000000..09948c7 --- /dev/null +++ b/python/rolemgmt_prereq_py.h @@ -0,0 +1,17 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#pragma once + +extern PyTypeObject rolemgmt_prereqType; diff --git a/python/rolemgmt_py.c b/python/rolemgmt_py.c new file mode 100644 index 0000000..54d56cd --- /dev/null +++ b/python/rolemgmt_py.c @@ -0,0 +1,502 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#include "includes.h" + +static char rolemgmt__doc__[] = ""; + +static void +rolemgmt_dealloc( + PY_ROLEMGMT *self + ) +{ + Py_TYPE(self)->tp_free((PyObject*)self); +} + +static PyObject * +rolemgmt_new( + PyTypeObject *type, + PyObject *args, + PyObject *kwds + ) +{ + PPY_ROLEMGMT self = NULL; + + self = (PPY_ROLEMGMT)type->tp_alloc(type, 0); + if (self != NULL) + { + } + + return (PyObject *)self; +} + +static int +rolemgmt_init( + PY_ROLEMGMT *self, + PyObject *args, + PyObject *kwds + ) +{ + PyObject *pRoles = NULL; + + if (! PyArg_ParseTuple(args, "O", &pRoles)) + { + return -1; + } + + return 0; +} + +PyObject* +rolemgmt_py_get_version( + PPY_ROLEMGMT self, + void *closure) +{ + uint32_t dwError = 0; + char *pszVersion = NULL; + PyObject *pyVersion = Py_None; + + dwError = rolemgmt_get_version(self->hHandle, &pszVersion); + BAIL_ON_PMD_ERROR(dwError); + + pyVersion = PyBytes_FromString(pszVersion); + if(!pyVersion) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + +cleanup: + PMD_SAFE_FREE_MEMORY(pszVersion); + return pyVersion; +error: + pyVersion = NULL; + raise_exception(dwError); + goto cleanup; +} + +PyObject* +rolemgmt_py_get_roles( + PPY_ROLEMGMT self, + void *closure) +{ + uint32_t dwError = 0; + size_t nCount = 0; + size_t i = 0; + PPMD_ROLEMGMT_ROLE pRoles = NULL; + PPMD_ROLEMGMT_ROLE pRole = NULL; + PyObject *pPyRolesDict = Py_None; + + if(!self || !self->hHandle) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + pPyRolesDict = PyDict_New(); + + dwError = rolemgmt_get_roles(self->hHandle, &pRoles); + BAIL_ON_PMD_ERROR(dwError); + + for(pRole = pRoles; pRole; pRole = pRole->pNext) + { + PyObject *pPyRoleDict = Py_None; + PyObject *pPyRoleId = PyBytes_FromString(pRole->pszId); + + dwError = rolemgmt_role_py_make(pRole, &pPyRoleDict); + BAIL_ON_PMD_ERROR(dwError); + + if(PyDict_SetItem(pPyRolesDict, pPyRoleId, pPyRoleDict) == -1) + { + dwError = ERROR_PMD_OUT_OF_MEMORY; + BAIL_ON_PMD_ERROR(dwError); + } + } + +cleanup: + rolemgmt_free_roles(pRoles); + return pPyRolesDict; + +error: + pPyRolesDict = NULL; + raise_exception(dwError); + goto cleanup; +} + +PyObject * +rolemgmt_py_role_version( + PPY_ROLEMGMT self, + PyObject *arg, + PyObject *kwds + ) +{ + uint32_t dwError = 0; + char *pszRoleName = NULL; + char *pszRoleVersion = NULL; + static char *kwlist[] = {"name", NULL}; + PyObject *pyRoleVersion = Py_None; + + if(!self || !self->hHandle) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if (!PyArg_ParseTupleAndKeywords( + arg, kwds, "s", kwlist, + &pszRoleName)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = rolemgmt_get_role_version( + self->hHandle, + pszRoleName, + &pszRoleVersion); + BAIL_ON_PMD_ERROR(dwError); + + pyRoleVersion = PyBytes_FromString(pszRoleVersion); + if(!pyRoleVersion) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + +cleanup: + return pyRoleVersion; + +error: + pyRoleVersion = NULL; + raise_exception(dwError); + goto cleanup; +} + +PyObject * +rolemgmt_py_prereqs( + PPY_ROLEMGMT self, + PyObject *arg, + PyObject *kwds + ) +{ + uint32_t dwError = 0; + char *pszRoleName = NULL; + PPMD_ROLE_PREREQ pPrereqs = NULL; + uint32_t i = 0; + uint32_t dwPrereqCount = 0; + PMD_ROLE_OPERATION nOperation = ROLE_OPERATION_NONE; + static char *kwlist[] = {"name", NULL}; + PPY_ROLEMGMT_PREREQ pPyPrereq = NULL; + PyObject *pyPrereqList = NULL; + + if(!self || !self->hHandle) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if (!PyArg_ParseTupleAndKeywords( + arg, kwds, "s", kwlist, + &pszRoleName)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = rolemgmt_get_prereqs( + self->hHandle, + pszRoleName, + nOperation, + &pPrereqs, + &dwPrereqCount); + BAIL_ON_PMD_ERROR(dwError); + + pyPrereqList = PyList_New(0); + + for(i = 0; i < dwPrereqCount; ++i) + { + dwError = rolemgmt_prereq_py_make( + &pPrereqs[i], + &pPyPrereq); + BAIL_ON_PMD_ERROR(dwError); + + if(PyList_Append(pyPrereqList, (PyObject *)pPyPrereq) == -1) + { + dwError = ERROR_PMD_OUT_OF_MEMORY; + BAIL_ON_PMD_ERROR(dwError); + } + } + +cleanup: + return pyPrereqList; + +error: + pyPrereqList = NULL; + raise_exception(dwError); + goto cleanup; +} + +PyObject * +rolemgmt_py_task_status( + PPY_ROLEMGMT self, + PyObject *arg, + PyObject *kwds + ) +{ + uint32_t dwError = 0; + char *pszRoleName = NULL; + char *pszTaskUUID = NULL; + static char *kwlist[] = {"name", "taskid", NULL}; + PyObject *pyTaskStatus = Py_None; + PMD_ROLE_STATUS nStatus = ROLE_STATUS_NONE; + + if(!self || !self->hHandle) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if (!PyArg_ParseTupleAndKeywords( + arg, kwds, "ss", kwlist, + &pszRoleName, &pszTaskUUID)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = rolemgmt_get_status( + self->hHandle, + pszRoleName, + pszTaskUUID, + &nStatus); + BAIL_ON_PMD_ERROR(dwError); + + pyTaskStatus = Py_BuildValue("i", nStatus); + +cleanup: + return pyTaskStatus; + +error: + pyTaskStatus = NULL; + raise_exception(dwError); + goto cleanup; +} + +PyObject * +rolemgmt_py_alter( + PPY_ROLEMGMT self, + PyObject *arg, + PyObject *kwds + ) +{ + uint32_t dwError = 0; + char *pszRoleName = NULL; + char *pszConfig = NULL; + PMD_ROLE_OPERATION nOperation = ROLE_OPERATION_NONE; + char *pszTaskUUID = NULL; + PyObject *pyTaskID = NULL; + static char *kwlist[] = {"name", "operation", "config", NULL}; + + if(!self || !self->hHandle) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if (!PyArg_ParseTupleAndKeywords( + arg, kwds, "sIs", kwlist, + &pszRoleName, &nOperation, &pszConfig)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if(nOperation <= ROLE_OPERATION_NONE || nOperation >= ROLE_OPERATION_MAX) + { + dwError = ERROR_PMD_ROLE_BAD_OPERATION; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = rolemgmt_alter( + self->hHandle, + pszRoleName, + nOperation, + pszConfig, + &pszTaskUUID); + BAIL_ON_PMD_ERROR(dwError); + + pyTaskID = PyBytes_FromString(pszTaskUUID); + +cleanup: + return pyTaskID; + +error: + pyTaskID = NULL; + raise_exception(dwError); + goto cleanup; +} + +PyObject * +rolemgmt_py_logs( + PPY_ROLEMGMT self, + PyObject *arg, + PyObject *kwds + ) +{ + uint32_t dwError = 0; + uint32_t i = 0; + char *pszTaskUUID = NULL; + int nStartAt = 0; + int nNumLogs = 0; + PPMD_ROLEMGMT_TASK_LOG pTaskLogs = NULL; + uint32_t dwLogCount = 0; + PyObject *pyTaskLogList = NULL; + PPY_ROLEMGMT_LOG_ENTRY pPyLogEntry = NULL; + + static char *kwlist[] = {"taskid", "startat", "numlogs", NULL}; + + if(!self || !self->hHandle) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if (!PyArg_ParseTupleAndKeywords( + arg, kwds, "sII", kwlist, + &pszTaskUUID, &nStartAt, &nNumLogs)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = rolemgmt_get_log( + self->hHandle, + pszTaskUUID, + nStartAt, + nNumLogs, + &pTaskLogs, + &dwLogCount); + BAIL_ON_PMD_ERROR(dwError); + + pyTaskLogList = PyList_New(0); + + for(i = 0; i < dwLogCount; ++i) + { +printf("i = %d\n", i); + dwError = rolemgmt_logentry_py_make( + &pTaskLogs[i], + &pPyLogEntry); + BAIL_ON_PMD_ERROR(dwError); +printf("i = %d\n", i); + + if(PyList_Append(pyTaskLogList, (PyObject *)pPyLogEntry) == -1) + { + dwError = ERROR_PMD_OUT_OF_MEMORY; + BAIL_ON_PMD_ERROR(dwError); + } + } + +cleanup: + return pyTaskLogList; + +error: + pyTaskLogList = NULL; + raise_exception(dwError); + goto cleanup; +} + +static PyGetSetDef rolemgmt_getset[] = { + {"version", + (getter)rolemgmt_py_get_version, (setter)NULL, + "get rolemgmt version", + NULL}, + {"roles", + (getter)rolemgmt_py_get_roles, (setter)NULL, + "get all registered roles", + NULL}, + {NULL} /* Sentinel */ +}; + +static PyMethodDef rolemgmt_methods[] = +{ + {"role_version", (PyCFunction)rolemgmt_py_role_version, METH_VARARGS|METH_KEYWORDS, + "rolemgmt.role_version(name=) \n\ + returns the version of a role by making a query to the plugin.\n\ + returns version if successful.\n"}, + {"prereqs", (PyCFunction)rolemgmt_py_prereqs, METH_VARARGS|METH_KEYWORDS, + "rolemgmt.prereqs(name=) \n\ + returns the prereqs of a role by making a query to the plugin.\n\ + returns list of prereqs if successful.\n"}, + {"status", (PyCFunction)rolemgmt_py_task_status, METH_VARARGS|METH_KEYWORDS, + "rolemgmt.status(name=, taskid=) \n\ + returns the status a role's task at the server.\n\ + returns status of role's task if successful.\n"}, + {"alter", (PyCFunction)rolemgmt_py_alter, METH_VARARGS|METH_KEYWORDS, + "rolemgmt.alter(name=,operation=,config=) \n\ + run the alter operation of a role at the server.\n\ + return new task id if successful.\n"}, + {"logs", (PyCFunction)rolemgmt_py_logs, METH_VARARGS|METH_KEYWORDS, + "rolemgmt.logs(taskid=,startat=,count=) \n\ + returns logs from an index for a task running at the server.\n\ + return logs if successful.\n"}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +static PyMemberDef rolemgmt_members[] = +{ + {NULL} /* Sentinel */ +}; + +PyTypeObject rolemgmtType = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "server.rolemgmt", /*tp_name*/ + sizeof(PY_ROLEMGMT), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)rolemgmt_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + rolemgmt__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + rolemgmt_methods, /* tp_methods */ + rolemgmt_members, /* tp_members */ + rolemgmt_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)rolemgmt_init, /* tp_init */ + 0, /* tp_alloc */ + rolemgmt_new, /* tp_new */ + 0, /* tp_free */ + 0 /* tp_is_gc */ +}; diff --git a/python/rolemgmt_py.h b/python/rolemgmt_py.h new file mode 100644 index 0000000..377fe7e --- /dev/null +++ b/python/rolemgmt_py.h @@ -0,0 +1,17 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#pragma once + +extern PyTypeObject rolemgmtType; diff --git a/python/rolemgmt_role_py.c b/python/rolemgmt_role_py.c new file mode 100644 index 0000000..d3b7b27 --- /dev/null +++ b/python/rolemgmt_role_py.c @@ -0,0 +1,274 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#include "includes.h" + +char rolemgmt_role__doc__[] = ""; + +void +rolemgmt_role_dealloc(PY_ROLEMGMT_ROLE *self) +{ + Py_XDECREF(self->id); + Py_XDECREF(self->name); + Py_XDECREF(self->displayname); + Py_XDECREF(self->description); + Py_TYPE(self)->tp_free((PyObject*)self); +} + +PyObject * +rolemgmt_role_new( + PyTypeObject *type, + PyObject *args, + PyObject *kwds) +{ + uint32_t dwError = 0; + PPY_ROLEMGMT_ROLE self = NULL; + + self = (PPY_ROLEMGMT_ROLE)type->tp_alloc(type, 0); + if (self != NULL) + { + if(!(self->id = PyBytes_FromString(""))) + { + dwError = ERROR_PMD_OUT_OF_MEMORY; + BAIL_ON_PMD_ERROR(dwError); + } + if(!(self->name = PyBytes_FromString(""))) + { + dwError = ERROR_PMD_OUT_OF_MEMORY; + BAIL_ON_PMD_ERROR(dwError); + } + if(!(self->displayname= PyBytes_FromString(""))) + { + dwError = ERROR_PMD_OUT_OF_MEMORY; + BAIL_ON_PMD_ERROR(dwError); + } + if(!(self->description = PyBytes_FromString(""))) + { + dwError = ERROR_PMD_OUT_OF_MEMORY; + BAIL_ON_PMD_ERROR(dwError); + } + } + +cleanup: + return (PyObject *)self; + +error: + Py_DECREF(self); + self = NULL; + goto cleanup; +} + +int +rolemgmt_role_init( + PY_ROLEMGMT_ROLE *self, + PyObject *args, + PyObject *kwds + ) +{ + uint32_t dwError = 0; + PyObject *id = NULL; + PyObject *name = NULL; + PyObject *displayname = NULL; + PyObject *description = NULL; + PyObject *tmp = NULL; + + static char *kwlist[] = {"id", "name", "displayname", "description", NULL}; + + if (!PyArg_ParseTupleAndKeywords( + args, kwds, "|SSSS", kwlist, + &id, &name, &displayname, &description)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if (id) + { + tmp = self->id; + Py_INCREF(id); + self->id = id; + Py_XDECREF(tmp); + } + if (name) + { + tmp = self->name; + Py_INCREF(name); + self->name = name; + Py_XDECREF(tmp); + } + if (displayname) + { + tmp = self->displayname; + Py_INCREF(displayname); + self->displayname = displayname; + Py_XDECREF(tmp); + } + if (description) + { + tmp = self->description; + Py_INCREF(description); + self->description = description; + Py_XDECREF(tmp); + } + +cleanup: + return dwError > 0 ? -1 : 0; + +error: + fprintf(stderr, "Error = %d\n", dwError); + goto cleanup; +} + +PyObject* +rolemgmt_role_repr( + PyObject *self + ) +{ + uint32_t dwError = 0; + PyObject *pyRepr = Py_None; + PPY_ROLEMGMT_ROLE pRole = NULL; + char *pszRepr = NULL; + + pRole = (PPY_ROLEMGMT_ROLE)self; + dwError = PMDAllocateStringPrintf( + &pszRepr, + "{id: %s, name: %s, displayname: %s, description: %s}", + pRole->id ? PyBytes_AsString(pRole->id) : "", + pRole->name ? PyBytes_AsString(pRole->name) : "", + pRole->displayname ? PyBytes_AsString(pRole->displayname) : "", + pRole->description ? PyBytes_AsString(pRole->description) : ""); + BAIL_ON_PMD_ERROR(dwError); + + pyRepr = Py_BuildValue("s", pszRepr); + Py_INCREF(pyRepr); + +cleanup: + PMD_SAFE_FREE_MEMORY(pszRepr); + return pyRepr; + +error: + pyRepr = NULL; + raise_exception(dwError); + goto cleanup; +} + +PyObject* +rolemgmt_role_str( + PyObject *self + ) +{ + return rolemgmt_role_repr(self); +} + +uint32_t +rolemgmt_role_py_make( + PPMD_ROLEMGMT_ROLE pRole, + PyObject **ppPyRole + ) +{ + uint32_t dwError = 0; + PPY_ROLEMGMT_ROLE pPyRole = NULL; + PyTypeObject *retType = &rolemgmt_roleType; + + if(!pRole || !ppPyRole) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + pPyRole = (PPY_ROLEMGMT_ROLE)retType->tp_alloc(retType, 0); + if(!pPyRole) + { + dwError = ERROR_PMD_OUT_OF_MEMORY; + BAIL_ON_PMD_ERROR(dwError); + } + + pPyRole->id = PyBytes_FromString(pRole->pszId); + pPyRole->name = PyBytes_FromString(pRole->pszName); + pPyRole->displayname = PyBytes_FromString(pRole->pszDisplayName ? pRole->pszDisplayName : ""); + pPyRole->description = PyBytes_FromString(pRole->pszDescription); + + *ppPyRole = (PyObject *)pPyRole; +cleanup: + return dwError; + +error: + Py_XDECREF(pPyRole); + pPyRole = NULL; + raise_exception(dwError); + goto cleanup; +} + +static PyGetSetDef rolemgmt_role_getset[] = { + {NULL} /* Sentinel */ +}; + +static PyMethodDef rolemgmt_role_methods[] = { + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +static PyMemberDef rolemgmt_role_members[] = { + {"id", T_OBJECT_EX, offsetof(PY_ROLEMGMT_ROLE, id), 0, + "role id"}, + {"name", T_OBJECT_EX, offsetof(PY_ROLEMGMT_ROLE, name), 0, + "role name"}, + {"displayname", T_OBJECT_EX, offsetof(PY_ROLEMGMT_ROLE, displayname), 0, + "role display name"}, + {"description", T_OBJECT_EX, offsetof(PY_ROLEMGMT_ROLE, description), 0, + "role description"}, + {NULL} /* Sentinel */ +}; + +PyTypeObject rolemgmt_roleType = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "rolemgmt_role", /*tp_name*/ + sizeof(PY_ROLEMGMT_ROLE), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)rolemgmt_role_dealloc,/*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + rolemgmt_role_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + rolemgmt_role_str, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + rolemgmt_role__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + rolemgmt_role_methods, /* tp_methods */ + rolemgmt_role_members, /* tp_members */ + rolemgmt_role_getset, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + (initproc)rolemgmt_role_init, /* tp_init */ + 0, /* tp_alloc */ + rolemgmt_role_new, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ +}; diff --git a/python/rolemgmt_role_py.h b/python/rolemgmt_role_py.h new file mode 100644 index 0000000..82b51d9 --- /dev/null +++ b/python/rolemgmt_role_py.h @@ -0,0 +1,17 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#pragma once + +extern PyTypeObject rolemgmt_roleType; diff --git a/python/server_py.c b/python/server_py.c index c2dc17a..2090f1e 100644 --- a/python/server_py.c +++ b/python/server_py.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" static char server__doc__[] = ""; @@ -227,6 +226,42 @@ server_getpkg( goto cleanup; } +static PyObject * +server_get_rolemgmt( + PPY_PMD_SERVER self, + void *closure) +{ + uint32_t dwError = 0; + PPMDHANDLE hHandle = NULL; + PPY_ROLEMGMT pRolemgmt = NULL; + PyObject *pyRolemgmt = NULL; + PyTypeObject *retType = &rolemgmtType; + + dwError = rpc_open("rolemgmt", + string_from_py_string(self->name), + string_from_py_string(self->user), + string_from_py_string(self->domain), + string_from_py_string(self->pass), + string_from_py_string(self->spn), + &hHandle); + if(dwError > 0) + { + goto error; + } + + pRolemgmt = (PPY_ROLEMGMT)retType->tp_alloc(retType, 0); + pRolemgmt->hHandle = hHandle; + pRolemgmt->server = (PyObject *)self; + + pyRolemgmt = (PyObject *)pRolemgmt; + +cleanup: + return pyRolemgmt; +error: + pyRolemgmt = Py_None; + goto cleanup; +} + static PyGetSetDef server_getset[] = { {"firewall", (getter)server_get_firewall, (setter)NULL, @@ -240,6 +275,10 @@ static PyGetSetDef server_getset[] = { (getter)server_getpkg, (setter)NULL, "pkgmgmt interface", NULL}, + {"rolemgmt", + (getter)server_get_rolemgmt, (setter)NULL, + "pkgmgmt interface", + NULL}, {NULL} /* Sentinel */ }; diff --git a/python/setup.py.in b/python/setup.py.in index 823ab5f..9f5cbf9 100644 --- a/python/setup.py.in +++ b/python/setup.py.in @@ -1,5 +1,5 @@ # -# Copyright (c) 2016-2017 VMware, Inc. All Rights Reserved. +# Copyright (c) 2016-2019 VMware, Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy @@ -11,7 +11,6 @@ # License for the specific language governing permissions and limitations # under the License. - from distutils.core import setup, Extension import os @@ -28,8 +27,10 @@ pmdmodule = Extension('pmd._pmd', 'netmgmt_py.c', 'netmgmt_link_py.c', 'netmgmt_route_py.c', 'netmgmt_system_py.c', 'pkgmgmt_py.c', 'pkgmgmt_repodata_py.c', - 'pkgmgmt_package_py.c', 'pkgmgmt_solvedinfo_py.c', - 'pkgmgmt_utils.c', + 'pkgmgmt_solvedinfo_py.c', + 'pkgmgmt_package_py.c', 'pkgmgmt_utils.c', + 'rolemgmt_py.c', 'rolemgmt_prereq_py.c', + 'rolemgmt_logentry_py.c', 'rolemgmt_role_py.c', 'pmdmodule.c', 'server_py.c', 'utils.c'], diff --git a/python/structs.h b/python/structs.h index 4748993..9402705 100644 --- a/python/structs.h +++ b/python/structs.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #pragma once typedef struct _PY_PMD_ @@ -87,3 +86,33 @@ typedef struct _PY_FIREWALL_ PyObject *server; PPMDHANDLE hHandle; }PY_FIREWALL, *PPY_FIREWALL; + +typedef struct _PY_ROLEMGMT_ +{ + PyObject_HEAD + PyObject *server; + PPMDHANDLE hHandle; +}PY_ROLEMGMT, *PPY_ROLEMGMT; + +typedef struct _PY_ROLEMGMT_ROLE_ +{ + PyObject_HEAD + PyObject *id; + PyObject *name; + PyObject *displayname; + PyObject *description; +}PY_ROLEMGMT_ROLE, *PPY_ROLEMGMT_ROLE; + +typedef struct _PY_ROLEMGMT_PREREQ_ +{ + PyObject_HEAD + PyObject *name; + PyObject *description; +}PY_ROLEMGMT_PREREQ, *PPY_ROLEMGMT_PREREQ; + +typedef struct _PY_ROLEMGMT_LOG_ENTRY_ +{ + PyObject_HEAD + long tStamp; + PyObject *log; +}PY_ROLEMGMT_LOG_ENTRY, *PPY_ROLEMGMT_LOG_ENTRY; diff --git a/python/utils.c b/python/utils.c index 7c63096..a6147c2 100644 --- a/python/utils.c +++ b/python/utils.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" static const char *szLinkStateString[] = @@ -144,7 +143,35 @@ py_string_as_string( *ppString = pString; cleanup: return dwError; +error: + goto cleanup; +} + +void +raise_exception( + uint32_t dwErrorCode + ) +{ + uint32_t dwError = 0; + char *pszError = NULL; + char *pszMessage = NULL; + + dwError = PMDGetErrorString(dwErrorCode, &pszError); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateStringPrintf(&pszMessage, + "Error = %d: %s", + dwErrorCode, + pszError); + BAIL_ON_PMD_ERROR(dwError); + + PyErr_SetString(PyExc_Exception, pszMessage); + +cleanup: + PMD_SAFE_FREE_MEMORY(pszMessage); + PMD_SAFE_FREE_MEMORY(pszError); + return; error: goto cleanup; } diff --git a/server/Makefile.am b/server/Makefile.am index 7edf74f..6fdc4e9 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -32,6 +32,9 @@ pmd_SOURCES = \ pmd_sstub.c \ netmgmt_sstub.c \ privsephandlelist.c \ + rolemgmt_sstub.c \ + rpmostree_sstub.c \ + rpmostreeapi.c \ utils.c fwmgmt_sstub.c: @@ -48,18 +51,26 @@ netmgmt_sstub.c: usermgmt_sstub.c: cp ../idl/usermgmt_sstub.c . +rolemgmt_sstub.c: + cp ../idl/rolemgmt_sstub.c . + +rpmostree_sstub.c: + cp ../idl/rpmostree_sstub.c . CLEANFILES = \ fwmgmt_sstub.c \ pkgmgmt_sstub.c \ pmd_sstub.c \ netmgmt_sstub.c \ - usermgmt_sstub.c + usermgmt_sstub.c \ + rolemgmt_sstub.c \ + rpmostree_sstub.c SUBDIRS = common \ - security \ - restutils \ - extras + rolemgmt \ + security \ + restutils \ + extras if ENABLE_DEMO SUBDIRS += demo @@ -73,6 +84,7 @@ pmd_LDADD = \ @top_builddir@/server/security/libpmdsecurity.la \ @top_builddir@/server/common/libsrvcommon.la \ @top_builddir@/client/libpmdclient.la \ + @top_builddir@/server/rolemgmt/librolemgmt.la \ @DCERPC_LIBS@ \ @JANSSON_LIBS@ \ @CREST_LIBS@ \ diff --git a/server/config.c b/server/config.c index 98338ff..438cc3c 100644 --- a/server/config.c +++ b/server/config.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -125,6 +125,61 @@ pmd_get_rest_config( goto cleanup; } +uint32_t +pmd_get_roles_config( + PCONF_DATA pData, + PPMD_ROLES_CONFIG *ppRolesConfig + ) +{ + uint32_t dwError = 0; + PCONF_SECTION pSection = NULL; + PKEYVALUE pKeyValues = NULL; + PPMD_ROLES_CONFIG pRolesConfig = NULL; + + if(!pData || !ppRolesConfig) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = config_get_section(pData, PMD_CONFIG_ROLES_GROUP, &pSection); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateMemory(sizeof(PMD_ROLES_CONFIG), + (void **)&pRolesConfig); + BAIL_ON_PMD_ERROR(dwError); + + pKeyValues = pSection->pKeyValues; + for(; pKeyValues; pKeyValues = pKeyValues->pNext) + { + if(!strcmp(PMD_CONFIG_KEY_ROLES_DIR, pKeyValues->pszKey)) + { + dwError = PMDAllocateString(pKeyValues->pszValue, + &pRolesConfig->pszDir); + BAIL_ON_PMD_ERROR(dwError); + } + else if(!strcmp(PMD_CONFIG_KEY_ROLES_PLUGINSDIR, pKeyValues->pszKey)) + { + dwError = PMDAllocateString(pKeyValues->pszValue, + &pRolesConfig->pszPluginsDir); + BAIL_ON_PMD_ERROR(dwError); + } + } + + *ppRolesConfig = pRolesConfig; + +cleanup: + return dwError; + +error: + if(ppRolesConfig) + { + *ppRolesConfig = NULL; + } + pmd_free_roles_config(pRolesConfig); + goto cleanup; +} + uint32_t pmd_read_config( const char* pszFile, @@ -189,6 +244,9 @@ pmd_read_config( dwError = pmd_get_rest_config(pData, &pConf->pRestConfig); BAIL_ON_PMD_ERROR(dwError); + dwError = pmd_get_roles_config(pData, &pConf->pRolesConfig); + BAIL_ON_PMD_ERROR(dwError); + *ppConf = pConf; cleanup: @@ -220,6 +278,20 @@ pmd_free_rest_config( PMD_SAFE_FREE_MEMORY(pRestConf); } +void +pmd_free_roles_config( + PPMD_ROLES_CONFIG pRolesConf + ) +{ + if(!pRolesConf) + { + return; + } + PMD_SAFE_FREE_MEMORY(pRolesConf->pszDir); + PMD_SAFE_FREE_MEMORY(pRolesConf->pszPluginsDir); + PMD_SAFE_FREE_MEMORY(pRolesConf); +} + void pmd_free_config( PPMD_CONFIG pConf @@ -235,5 +307,6 @@ pmd_free_config( PMD_SAFE_FREE_MEMORY(pConf->pszApiSecurityConf); pmd_free_rest_config(pConf->pRestConfig); PMD_SAFE_FREE_MEMORY(pConf->pszPrivsepPubKeyFile); + pmd_free_roles_config(pConf->pRolesConfig); PMD_SAFE_FREE_MEMORY(pConf); } diff --git a/server/defines.h b/server/defines.h index 3d1d80d..02755a3 100644 --- a/server/defines.h +++ b/server/defines.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #pragma once typedef struct _PMDHANDLE_* PPMDHANDLE; @@ -28,6 +27,16 @@ typedef struct _PMDHANDLE_* PPMDHANDLE; #define PMD_CONFIG_MAIN_GROUP "main" #define PMD_CONFIG_REST_GROUP "rest-server" #define PMD_CONFIG_PRIVSEP_GROUP "privsep" +#define BAIL_ON_PMD_SYSTEM_ERROR(dwError) \ + do { \ + if (dwError) \ + { \ + dwError = ERROR_PMD_SYSTEM_BASE + dwError; \ + goto error; \ + } \ + } while(0) + +#define PMD_CONFIG_ROLES_GROUP "roles" #define PMD_CONFIG_KEY_REST_ENABLED "enabled" #define PMD_CONFIG_KEY_REST_PORT "port" @@ -39,11 +48,14 @@ typedef struct _PMDHANDLE_* PPMDHANDLE; #define PMD_CONFIG_KEY_REST_CLIENT_COUNT "client-count" #define PMD_CONFIG_KEY_REST_LOG_FILE "logfile" -#define PMD_CONFIG_KEY_SERVERTYPE "servertype" -#define PMD_CONFIG_KEY_CURRENTHASH "currenthash" -#define PMD_CONFIG_KEY_SERVERURL "serverurl" -#define PMD_CONFIG_KEY_COMPOSESERVER "composeserver" -#define PMD_CONFIG_KEY_API_SECURITY "apisecurity" +#define PMD_CONFIG_KEY_SERVERTYPE "servertype" +#define PMD_CONFIG_KEY_CURRENTHASH "currenthash" +#define PMD_CONFIG_KEY_SERVERURL "serverurl" +#define PMD_CONFIG_KEY_COMPOSESERVER "composeserver" +#define PMD_CONFIG_KEY_API_SECURITY "apisecurity" + +#define PMD_CONFIG_KEY_ROLES_DIR "dir" +#define PMD_CONFIG_KEY_ROLES_PLUGINSDIR "pluginsdir" #define PMD_CONFIG_KEY_PRIVSEP_PUBKEY "pubkey" #define PMD_CONFIG_KEY_PRIVSEP_PRIVKEY "privkey" diff --git a/server/global.c b/server/global.c index 2c2cf1d..24eaaca 100644 --- a/server/global.c +++ b/server/global.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" PSERVER_ENV gpServerEnv = NULL; diff --git a/server/includes.h b/server/includes.h index 61d5c44..1c2be75 100644 --- a/server/includes.h +++ b/server/includes.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #pragma once #include @@ -38,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -52,6 +52,8 @@ #include "../idl/fwmgmt_h.h" #include "../idl/pmd_h.h" #include "../idl/netmgmt_h.h" +#include "../idl/rpmostree_h.h" +#include "../idl/rolemgmt_h.h" #include "../idl/usermgmt_h.h" #include "../common/includes.h" diff --git a/server/netmgmtrestapi.c b/server/netmgmtrestapi.c index 75e9506..5e951be 100644 --- a/server/netmgmtrestapi.c +++ b/server/netmgmtrestapi.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" #include diff --git a/server/prototypes.h b/server/prototypes.h index 59352b2..8abae75 100644 --- a/server/prototypes.h +++ b/server/prototypes.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #pragma once //netmgmtrestapi.c uint32_t @@ -851,6 +850,11 @@ pkg_get_scope_from_string( TDNF_SCOPE *pnScope ); +uint32_t +rolemgmt_rest_get_registration( + PREST_MODULE *ppRestModule + ); + void TDNFFreeCmdArgs( PTDNF_CMD_ARGS pCmdArgs @@ -998,6 +1002,17 @@ usermgmt_get_groupid_w( uint32_t *pnGID ); +void +pmd_free_rest_config( + PPMD_REST_CONFIG pRestConf + ); + +void +pmd_free_roles_config( + PPMD_ROLES_CONFIG pRolesConf + ); + +//utils.c uint32_t usermgmt_get_users_w( PPMDHANDLE hHandle, @@ -1022,6 +1037,16 @@ usermgmt_delete_user_w( const wstring_t pwszName ); +//rolemgmt_api.c +uint32_t +pmd_rolemgmt_load( + ); + +uint32_t +pmd_rolemgmt_unload( + ); + +//restserver.c uint32_t usermgmt_add_group_w( PPMDHANDLE hHandle, diff --git a/server/restserver.c b/server/restserver.c index 58b3d15..b8addb2 100644 --- a/server/restserver.c +++ b/server/restserver.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -35,6 +35,7 @@ StartRestServer( {"net", net_rest_get_registration}, {"pkg", pkg_rest_get_registration}, {"pmd", pmd_rest_get_registration}, + {"rolemgmt",rolemgmt_rest_get_registration}, {"usrmgmt", usrmgmt_rest_get_registration}, {NULL, NULL} diff --git a/server/restutils/restauth.c b/server/restutils/restauth.c index e424eec..1283bd8 100644 --- a/server/restutils/restauth.c +++ b/server/restutils/restauth.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -46,52 +46,6 @@ request_basic_auth( return dwError; } -//this path is not in rest basic auth anymore -uint32_t -populate_error( - PVMREST_HANDLE pRestHandle, - PREST_RESPONSE* ppResponse, - PJWT_ERROR pError - ) -{ - uint32_t dwError = 0; - char *pszCode = NULL; - uint32_t temp = 0; - - if(!pRestHandle || !ppResponse || !pError) - { - dwError = ERROR_PMD_INVALID_PARAMETER; - BAIL_ON_PMD_ERROR(dwError); - } - - dwError = PMDAllocateStringPrintf(&pszCode, "%d", pError->nStatus); - BAIL_ON_PMD_ERROR(dwError); - - dwError = VmRESTSetHttpStatusVersion(ppResponse, "HTTP/1.1"); - BAIL_ON_PMD_ERROR(dwError); - - dwError = VmRESTSetHttpStatusCode(ppResponse, pszCode); - BAIL_ON_PMD_ERROR(dwError); - - dwError = VmRESTSetHttpReasonPhrase(ppResponse, pError->pszError); - BAIL_ON_PMD_ERROR(dwError); - - dwError = VmRESTSetHttpHeader(ppResponse, "Connection", "close"); - BAIL_ON_PMD_ERROR(dwError); - - dwError = VmRESTSetHttpHeader(ppResponse, "Content-Length", "0"); - BAIL_ON_PMD_ERROR(dwError); - - dwError = VmRESTSetHttpPayload(pRestHandle, ppResponse, "", 0, &temp); - BAIL_ON_PMD_ERROR(dwError); - -cleanup: - PMD_SAFE_FREE_MEMORY(pszCode); - return dwError; - -error: - goto cleanup; -} uint32_t pre_process_auth( diff --git a/server/restutils/restbasicauth.c b/server/restutils/restbasicauth.c new file mode 100644 index 0000000..dc755fe --- /dev/null +++ b/server/restutils/restbasicauth.c @@ -0,0 +1,113 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#include "includes.h" + +/* +HTTP/1.1 401 Authorization Required +WWW-Authenticate: Basic realm="Photon Management Daemon" +Content-Type: text/html +Content-Length: 20 +*/ + +uint32_t +request_basic_auth( + PVMREST_HANDLE pRestHandle, + PREST_REQUEST pRequest, + PREST_RESPONSE* ppResponse + ) +{ + uint32_t dwError = 0; + uint32_t temp = 0; + + dwError = VmRESTSetHttpStatusVersion(ppResponse, "HTTP/1.1"); + dwError = VmRESTSetHttpStatusCode(ppResponse, "401"); + dwError = VmRESTSetHttpReasonPhrase(ppResponse, "Unauthorized"); + dwError = VmRESTSetHttpHeader(ppResponse, "Connection", "close"); + dwError = VmRESTSetHttpHeader(ppResponse, "Content-Length", "0"); + dwError = VmRESTSetHttpHeader(ppResponse, "WWW-Authenticate", "Basic realm=\"Photon Management Daemon\""); + dwError = VmRESTSetHttpPayload(pRestHandle, ppResponse,"", 0, &temp ); + dwError = EACCES; + return dwError; +} + +uint32_t +verify_basic_auth( + PVMREST_HANDLE pRestHandle, + PREST_REQUEST pRequest, + PREST_RESPONSE* ppResponse + ) +{ + uint32_t dwError = 0; + char* pszAuth = NULL; + const char* BASIC_AUTH_STRING = "Basic "; + char* pszUserPassBase64 = NULL; + char* pszUserPass = NULL; + char* pszUser = NULL; + char* pszPass = NULL; + int nLength = 0; + uint32_t nValid = 0; + + dwError = VmRESTGetHttpHeader(pRequest, "Authorization", &pszAuth); + BAIL_ON_PMD_ERROR(dwError); + + if(!pszAuth) + { + dwError = EACCES; + BAIL_ON_PMD_ERROR(dwError); + } + + if(!strstr(pszAuth, BASIC_AUTH_STRING)) + { + dwError = EACCES; + BAIL_ON_PMD_ERROR(dwError); + } + + pszUserPassBase64 = pszAuth + strlen(BASIC_AUTH_STRING); + if(IsNullOrEmptyString(pszUserPassBase64)) + { + dwError = EACCES; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = base64_decode(pszUserPassBase64, &pszUserPass, &nLength); + BAIL_ON_PMD_ERROR(dwError); + + dwError = split_user_and_pass(pszUserPass, &pszUser, &pszPass); + BAIL_ON_PMD_ERROR(dwError); + + //validate local user/pass + dwError = pmd_check_password(pszUser, pszPass, &nValid); + BAIL_ON_PMD_ERROR(dwError); + + if(!nValid) + { + fprintf(stderr, "REST basic auth fail for user: %s\n", pszUser); + dwError = EACCES; + BAIL_ON_PMD_ERROR(dwError); + } + +cleanup: + PMD_SAFE_FREE_MEMORY(pszUserPass); + PMD_SAFE_FREE_MEMORY(pszUser); + PMD_SAFE_FREE_MEMORY(pszPass); + return dwError; + +error: + if(dwError == EACCES || dwError == ERROR_PMD_ACCESS_DENIED) + { + request_basic_auth(pRestHandle, pRequest, ppResponse); + } + goto cleanup; +} diff --git a/server/restutils/restutils.c b/server/restutils/restutils.c index cd0509f..f4f854f 100644 --- a/server/restutils/restutils.c +++ b/server/restutils/restutils.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" PREST_API_DEF gpApiDef = NULL; @@ -30,7 +29,7 @@ rest_register_api_spec( PREST_API_MODULE pModule = NULL; PREST_PROCESSOR pRestProcessor = NULL; - if(!pRestHandle || !pApiDef || !ppRestProcessor) + if(!pApiDef || !ppRestProcessor || !pRestHandle) { dwError = ERROR_PMD_INVALID_PARAMETER; BAIL_ON_PMD_ERROR(dwError); @@ -52,10 +51,10 @@ rest_register_api_spec( for(; pEndPoint; pEndPoint = pEndPoint->pNext) { dwError = VmRESTRegisterHandler( - pRestHandle, - pEndPoint->pszName, - pRestProcessor, - NULL); + pRestHandle, + pEndPoint->pszName, + pRestProcessor, + NULL); BAIL_ON_PMD_ERROR(dwError); } } @@ -375,7 +374,6 @@ find_in_module( goto cleanup; } - uint32_t get_uri_from_request( PREST_REQUEST pRequest, @@ -460,6 +458,51 @@ find_module_entry_spec( goto cleanup; } +uint32_t +populate_error( + PVMREST_HANDLE pRestHandle, + PREST_RESPONSE* ppResponse, + PJWT_ERROR pError + ) +{ + uint32_t dwError = 0; + char *pszCode = NULL; + uint32_t temp = 0; + + if(!pRestHandle || !ppResponse || !pError) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + dwError = PMDAllocateStringPrintf(&pszCode, "%d", pError->nStatus); + BAIL_ON_PMD_ERROR(dwError); + + dwError = VmRESTSetHttpStatusVersion(ppResponse, "HTTP/1.1"); + BAIL_ON_PMD_ERROR(dwError); + + dwError = VmRESTSetHttpStatusCode(ppResponse, pszCode); + BAIL_ON_PMD_ERROR(dwError); + + dwError = VmRESTSetHttpReasonPhrase(ppResponse, pError->pszError); + BAIL_ON_PMD_ERROR(dwError); + + dwError = VmRESTSetHttpHeader(ppResponse, "Connection", "close"); + BAIL_ON_PMD_ERROR(dwError); + + dwError = VmRESTSetHttpHeader(ppResponse, "Content-Length", "0"); + BAIL_ON_PMD_ERROR(dwError); + + dwError = VmRESTSetHttpPayload(pRestHandle, ppResponse, "", 0, &temp); + BAIL_ON_PMD_ERROR(dwError); + +cleanup: + PMD_SAFE_FREE_MEMORY(pszCode); + return dwError; + +error: + goto cleanup; +} + uint32_t rest_method( PVMREST_HANDLE pRestHandle, diff --git a/server/rolemgmt/Makefile.am b/server/rolemgmt/Makefile.am new file mode 100644 index 0000000..b2ff41f --- /dev/null +++ b/server/rolemgmt/Makefile.am @@ -0,0 +1,29 @@ +noinst_LTLIBRARIES = librolemgmt.la + +librolemgmt_la_CPPFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/idl \ + @LW_INCLUDES@ \ + @UUID_CFLAGS@ + +librolemgmt_la_SOURCES = \ + rolemgmt_api.c \ + rolemgmt_config.c \ + rolemgmt_global.c \ + rolemgmt_plugin.c \ + rolemgmt_restapi.c \ + rolemgmt_rpcapi.c \ + rolemgmt_sstub.c + +rolemgmt_sstub.c: + cp ../../idl/rolemgmt_sstub.c . + +CLEANFILES = \ + rolemgmt_sstub.c + +librolemgmt_la_LDFLAGS = \ + -static \ + @top_builddir@/common/libcommon.la \ + @top_builddir@/jsonutils/libjsonutils.la \ + @UUID_LIBS@ \ + -ldl diff --git a/server/rolemgmt/defines.h b/server/rolemgmt/defines.h new file mode 100644 index 0000000..8245ac5 --- /dev/null +++ b/server/rolemgmt/defines.h @@ -0,0 +1,46 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#pragma once + +#define PMD_ROLEMGMT_VERSION "0.1" + +#define PMD_ROLE_EXT ".role" +#define PMD_ROLE_EXT_LEN 5 +#define PMD_ROLES_DIR "/etc/pmd.roles.d" +#define PMD_ROLE_PLUGINS_DIR "/etc/pmd.roles.plugins.d" + +#define ROLE_CONF_NAME "name" +#define ROLE_CONF_DISPLAY_NAME "displayname" +#define ROLE_CONF_DESCRIPTION "description" +#define ROLE_CONF_PARENT "parent" +#define ROLE_CONF_PLUGIN "plugin" + +#define UUID_STR_LEN 37 + +//Function name defs +#define PMD_ROLEPLUGIN_LOAD_INTERFACE "pmd_roleplugin_load_interface" +#define PMD_ROLEPLUGIN_UNLOAD_INTERFACE "pmd_roleplugin_unload_interface" + +//load +typedef uint32_t +(*PFN_PMD_ROLEPLUGIN_LOAD_INTERFACE)( + PPMD_ROLE_PLUGIN_INTERFACE *ppRoleInterface + ); + +//unload +typedef uint32_t +(*PFN_PMD_ROLEPLUGIN_UNLOAD_INTERFACE)( + PPMD_ROLE_PLUGIN_INTERFACE pRoleInterface + ); diff --git a/server/rolemgmt/includes.h b/server/rolemgmt/includes.h new file mode 100644 index 0000000..145cef8 --- /dev/null +++ b/server/rolemgmt/includes.h @@ -0,0 +1,50 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#pragma once +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "../../idl/rolemgmt_h.h" + +#include "../../common/defines.h" +#include "../../common/structs.h" +#include "../../common/prototypes.h" +#include "../../include/pmderror.h" +#include "../server/defines.h" +#include "defines.h" +#include "structs.h" + +#include "rolemgmt_global.h" + +#include "prototypes.h" +#include "../../jsonutils/prototypes.h" diff --git a/server/rolemgmt/prototypes.h b/server/rolemgmt/prototypes.h new file mode 100644 index 0000000..4de8a8c --- /dev/null +++ b/server/rolemgmt/prototypes.h @@ -0,0 +1,284 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#pragma once + +//rolemgmt_api.c - server api +uint32_t +pmd_rolemgmt_get_version( + char **ppszVersion + ); + +uint32_t +pmd_rolemgmt_get_roles( + PPMD_ROLEMGMT_ROLE *ppRoles + ); + +uint32_t +pmd_rolemgmt_role_version( + const char *pszName, + char **ppszVersion + ); + +uint32_t +pmd_rolemgmt_role_alter( + const char *pszName, + PMD_ROLE_OPERATION nOperation, + const char *pszConfigJson, + char **ppszTaskUUID + ); + +uint32_t +pmd_rolemgmt_role_get_prereqs( + const char *pszName, + PMD_ROLE_OPERATION nOperation, + PPMD_ROLE_PREREQ *ppPreReqs, + uint32_t *pdwPreReqCount + ); + +uint32_t +pmd_rolemgmt_alter_task_progress( + const char *pszTaskUUID, + const char *pszProgress + ); + +uint32_t +pmd_rolemgmt_get_status( + const char *pszName, + const char *pszTaskUUID, + PMD_ROLE_STATUS *pnStatus + ); + +uint32_t +pmd_rolemgmt_get_logs( + const char *pszTaskUUID, + uint32_t dwOffset, + uint32_t dwEntriesToFetch, + PPMD_PLUGIN_TASK_LOG *ppTaskLogs + ); + +uint32_t +rolemgmt_find_task_by_id( + const char *pszTaskUUID, + PPMD_PLUGIN_TASK *ppTask + ); + +uint32_t +rolemgmt_find_archived_task_by_id( + const char *pszTaskUUID, + PPMD_PLUGIN_TASK *ppTask + ); +void +rolemgmt_free_plugin_task_logs( + PPMD_PLUGIN_TASK_LOG pLogs + ); + +void +rolemgmt_free_plugin_module_task( + PPMD_PLUGIN_MODULE pModule + ); + +void +rolemgmt_free_plugin_module_tasks( + PPMD_PLUGIN_MODULE pModule + ); + +void +rolemgmt_free_context( + PPMD_PLUGIN_CONTEXT pContext + ); + +void +rolemgmt_free_contexts( + PPMD_PLUGIN_CONTEXT pContexts + ); + +//rolemgmt_rpcapi.c +void +rolemgmt_rpc_role_free_task_log_array( + PPMD_RPC_ROLEMGMT_TASK_LOG_ARRAY pTaskLogArray + ); + +void +rolemgmt_rpc_role_free_prereq_array( + PPMD_RPC_ROLEMGMT_PREREQ_ARRAY pPrereqArray + ); + +//rolemgmt_config.c + +uint32_t +rolemgmt_load_roles( + const char *pszRolesDir, + const char *pszPluginsDir, + PPMD_ROLEMGMT_ROLE *ppRoles + ); + +void +rolemgmt_free_role( + PPMD_ROLEMGMT_ROLE pRole + ); + +uint32_t +rolemgmt_move_role_children( + PPMD_ROLEMGMT_ROLE pRole, + PPMD_ROLEMGMT_ROLE *ppRoleArray, + int nRoleCount + ); + +uint32_t +rolemgmt_move_role_parents( + PPMD_CONFIG_ITEM pItems, + PPMD_ROLEMGMT_ROLE *ppRoleArray, + int nRoleCount, + PPMD_ROLEMGMT_ROLE *ppRoles + ); + +uint32_t +rolemgmt_copy_roles( + PPMD_CONFIG_ITEM pItems, + PPMD_ROLEMGMT_ROLE **ppRoles, + int *pnRoleCount + ); + +void +print_roles( + PPMD_ROLEMGMT_ROLE pRoles + ); + +void +print_items( + PPMD_CONFIG_ITEM pItems + ); + +uint32_t +rolemgmt_read_roles( + const char *pszRolesDir, + PPMD_CONFIG_ITEM *ppItems + ); + +uint32_t +rolemgmt_read_role( + const char *pszFile, + PPMD_CONFIG_ITEM *ppItems + ); + +uint32_t +rolemgmt_load_item_data( + PPMD_CONFIG_ITEM pRole, + PCONF_SECTION pSection + ); + +void +rolemgmt_free_roles( + PPMD_ROLEMGMT_ROLE pRoles + ); + +void +rolemgmt_free_item( + PPMD_CONFIG_ITEM pItem + ); + +void +rolemgmt_free_items( + PPMD_CONFIG_ITEM pItems + ); + +//rolemgmt_plugin.c +uint32_t +pmd_rolemgmt_plugin_get_version( + const PPMD_PLUGIN_MODULE pModule, + char **ppszVersion + ); + +uint32_t +pmd_rolemgmt_plugin_open( + const PPMD_PLUGIN_MODULE pModule, + PPMD_ROLE_HANDLE *ppRoleHandle + ); + +uint32_t +pmd_rolemgmt_plugin_close( + const PPMD_PLUGIN_MODULE pModule, + PPMD_ROLE_HANDLE pRoleHandle + ); + +uint32_t +pmd_rolemgmt_plugin_get_prereqs( + const PPMD_PLUGIN_MODULE pModule, + PMD_ROLE_OPERATION nOperation, + const PPMD_ROLE_HANDLE pRoleHandle, + PPMD_ROLE_PREREQ *ppPreReqs, + uint32_t *pdwPreReqCount + ); + +uint32_t +pmd_rolemgmt_plugin_alter( + const PPMD_PLUGIN_MODULE pModule, + const PPMD_PLUGIN_TASK pTask + ); +//rolemgmt_restapi.c +uint32_t +rolemgmt_rest_get_version( + void *pInputJson, + void **ppszOutputJson + ); + +uint32_t +rolemgmt_rest_get_roleversion( + void *pInputJson, + void **ppszOutputJson + ); + +uint32_t +rolemgmt_rest_get_roles( + void *pInputJson, + void **ppszOutputJson + ); + +uint32_t +rolemgmt_rest_get_status( + void *pInputJson, + void **ppszOutputJson + ); + +uint32_t +rolemgmt_rest_get_logs( + void *pInputJson, + void **ppszOutputJson + ); + +uint32_t +rolemgmt_rest_alter( + void *pInputJson, + void **ppszOutputJson + ); + +uint32_t +rolemgmt_rest_alter_put( + void *pInputJson, + void **ppszOutputJson + ); + +uint32_t +rolemgmt_rest_alter_delete( + void *pInputJson, + void **ppszOutputJson + ); + +uint32_t +rolemgmt_rest_alter_patch( + void *pInputJson, + void **ppszOutputJson + ); + diff --git a/server/rolemgmt/rolemgmt_api.c b/server/rolemgmt/rolemgmt_api.c new file mode 100644 index 0000000..25d87b6 --- /dev/null +++ b/server/rolemgmt/rolemgmt_api.c @@ -0,0 +1,951 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#include "includes.h" + + +uint32_t +pmd_rolemgmt_get_version( + char **ppszVersion + ) +{ + uint32_t dwError = 0; + char *pszVersion = NULL; + + if(!ppszVersion) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateString(PMD_ROLEMGMT_VERSION, &pszVersion); + BAIL_ON_PMD_ERROR(dwError); + + *ppszVersion = pszVersion; + +cleanup: + return dwError; + +error: + if(ppszVersion) + { + *ppszVersion = NULL; + } + goto cleanup; +} + +uint32_t +pmd_rolemgmt_load( + ) +{ + uint32_t dwError = 0; + int nLocked = 0, nPrefix = 0; + PPMD_ROLEMGMT_ROLE pRoles = NULL; + PPMD_ROLEMGMT_ROLE pRole = NULL; + PPMD_PLUGIN_CONTEXT pContexts = NULL; + PPMD_PLUGIN_CONTEXT pContext = NULL; + char pszResolvedPath[PATH_MAX]; + + pthread_mutex_lock(&gRoleMgmtEnv.mutexEnv); + nLocked = 1; + + if(gRoleMgmtEnv.pRoles) + { + goto cleanup; + } + + dwError = rolemgmt_load_roles( + PMD_ROLES_DIR, + PMD_ROLE_PLUGINS_DIR, + &pRoles); + BAIL_ON_PMD_ERROR(dwError); + + for(pRole = pRoles; pRole; pRole = pRole->pNext) + { + dwError = PMDAllocateMemory(sizeof(PMD_PLUGIN_CONTEXT), (void **)&pContext); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateString(pRole->pszId, &pContext->pszPluginId); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateStringPrintf( + &pContext->pszPluginPath, + "%s/%s", + PMD_ROLE_PLUGINS_DIR, + pRole->pszPlugin); + BAIL_ON_PMD_ERROR(dwError); + + if(NULL == realpath(pContext->pszPluginPath, pszResolvedPath)) + { + dwError = errno; + BAIL_ON_PMD_SYSTEM_ERROR(dwError); + } + BAIL_ON_PMD_ERROR(dwError); + + dwError = isStringPrefix(pszResolvedPath, + PMD_ROLE_PLUGINS_DIR, + &nPrefix); + BAIL_ON_PMD_ERROR(dwError); + + if(!nPrefix) + { + dwError = ERROR_PMD_ROLE_PATH_MISMATCH; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateMemory(sizeof(PMD_PLUGIN_MODULE), + (void **)&pContext->pModule); + BAIL_ON_PMD_ERROR(dwError); + + pContext->pNext = pContexts; + pContexts = pContext; + pContext = NULL; + } + + gRoleMgmtEnv.pRoles = pRoles; + gRoleMgmtEnv.pContexts = pContexts; + +cleanup: + if(nLocked) + { + pthread_mutex_unlock(&gRoleMgmtEnv.mutexEnv); + } + return dwError; + +error: + if(dwError == ERROR_PMD_NO_DATA)//no role files. don't fail. + { + dwError = 0; + } + gRoleMgmtEnv.pRoles = NULL; + gRoleMgmtEnv.pContexts = NULL; + + rolemgmt_free_roles(pRoles); + rolemgmt_free_context(pContext); + rolemgmt_free_contexts(pContexts); + goto cleanup; +} + +void +pmd_rolemgmt_unload( + ) +{ + pthread_mutex_lock(&gRoleMgmtEnv.mutexEnv); + + rolemgmt_free_roles(gRoleMgmtEnv.pRoles); + gRoleMgmtEnv.pRoles = NULL; + + rolemgmt_free_contexts(gRoleMgmtEnv.pContexts); + gRoleMgmtEnv.pContexts = NULL; + + pthread_mutex_unlock(&gRoleMgmtEnv.mutexEnv); +} + +uint32_t +pmd_load_plugin( + const char *pszPluginPath, + const PPMD_PLUGIN_MODULE pModule + ) +{ + uint32_t dwError = 0; + int nLocked = 0; + PMD_PLUGIN_MODULE stModule = {0}; + + if(IsNullOrEmptyString(pszPluginPath) || !pModule) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if(pModule->pHandle) + { + goto cleanup; + } + + if(pModule->nDisabled) + { + dwError = ERROR_PMD_ROLE_PLUGIN_DISABLED; + BAIL_ON_PMD_ERROR(dwError); + } + + pthread_mutex_lock(&pModule->mutexModule); + nLocked = 1; + + //clear error + dlerror(); + + stModule.pHandle = dlopen (pszPluginPath, RTLD_NOW); + if(!stModule.pHandle) + { + dwError = ERROR_PMD_LIBACC; + BAIL_ON_PMD_ERROR(dwError); + } + + stModule.pFnLoad = dlsym(stModule.pHandle, + PMD_ROLEPLUGIN_LOAD_INTERFACE); + if(!stModule.pFnLoad) + { + dwError = ERROR_PMD_ROLE_UNMAPPED_LOAD; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = stModule.pFnLoad(&stModule.pInterface); + BAIL_ON_PMD_ERROR(dwError); + + if(!stModule.pInterface) + { + dwError = ERROR_PMD_ROLE_PLUGIN_BAD; + BAIL_ON_PMD_ERROR(dwError); + } + + //unload can be null. + stModule.pFnUnload = dlsym(stModule.pHandle, + PMD_ROLEPLUGIN_UNLOAD_INTERFACE); + + pModule->pHandle = stModule.pHandle; + pModule->pFnLoad = stModule.pFnLoad; + pModule->pFnUnload = stModule.pFnUnload; + pModule->pInterface = stModule.pInterface; + +cleanup: + if(nLocked) + { + pthread_mutex_unlock(&pModule->mutexModule); + } + return dwError; + +error: + fprintf(stderr, "Error: %d, dlerror: %s", dwError, dlerror()); + if(pModule) + { + pModule->nDisabled = 1; + } + if(stModule.pHandle) + { + dlclose(stModule.pHandle); + } + goto cleanup; +} + +uint32_t +pmd_rolemgmt_get_role_plugin( + const char *pszName, + PPMD_PLUGIN_MODULE *ppModule + ) +{ + uint32_t dwError = 0; + PPMD_PLUGIN_CONTEXT pContext = NULL; + PPMD_PLUGIN_MODULE pModule = NULL; + + if(IsNullOrEmptyString(pszName) || !ppModule) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + for(pContext = gRoleMgmtEnv.pContexts; pContext; pContext = pContext->pNext) + { + if(!strcasecmp(pContext->pszPluginId, pszName)) + { + break; + } + } + + if(!pContext || !pContext->pModule) + { + dwError = ERROR_PMD_ROLES_NO_SUCH_ROLE; + BAIL_ON_PMD_ERROR(dwError); + } + + pModule = pContext->pModule; + if(!pModule->pHandle) + { + if(IsNullOrEmptyString(pContext->pszPluginPath)) + { + dwError = ERROR_PMD_ROLES_PLUGIN_NOT_SET; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = pmd_load_plugin(pContext->pszPluginPath, pModule); + BAIL_ON_PMD_ERROR(dwError); + } + + *ppModule = pModule; + +cleanup: + return dwError; + +error: + if(ppModule) + { + *ppModule = NULL; + } + goto cleanup; +} + +uint32_t +pmd_rolemgmt_role_version( + const char *pszName, + char **ppszVersion + ) +{ + uint32_t dwError = 0; + char *pszVersion = NULL; + char *pszPlugin = NULL; + PPMD_PLUGIN_MODULE pModule = NULL; + + if(IsNullOrEmptyString(pszName) || !ppszVersion) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = pmd_rolemgmt_get_role_plugin(pszName, &pModule); + BAIL_ON_PMD_ERROR(dwError); + + dwError = pmd_rolemgmt_plugin_get_version(pModule, &pszVersion); + BAIL_ON_PMD_ERROR(dwError); + + *ppszVersion = pszVersion; + +cleanup: + return dwError; + +error: + if(ppszVersion) + { + *ppszVersion = NULL; + } + PMD_SAFE_FREE_MEMORY(pszVersion); + goto cleanup; +} + +uint32_t +pmd_rolemgmt_role_get_prereqs( + const char *pszName, + PMD_ROLE_OPERATION nOperation, + PPMD_ROLE_PREREQ *ppPreReqs, + uint32_t *pdwPreReqCount + ) +{ + uint32_t dwError = 0; + PPMD_PLUGIN_MODULE pModule = NULL; + PPMD_ROLE_PREREQ pPreReqs = NULL; + uint32_t dwPreReqCount = 0; + PPMD_ROLE_HANDLE pRoleHandle = NULL; + + if(!ppPreReqs || !pdwPreReqCount) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = pmd_rolemgmt_get_role_plugin(pszName, &pModule); + BAIL_ON_PMD_ERROR(dwError); + + dwError = pmd_rolemgmt_plugin_open(pModule, &pRoleHandle); + BAIL_ON_PMD_ERROR(dwError); + + dwError = pmd_rolemgmt_plugin_get_prereqs( + pModule, + nOperation, + pRoleHandle, + &pPreReqs, + &dwPreReqCount); + BAIL_ON_PMD_ERROR(dwError); + + *ppPreReqs = pPreReqs; + *pdwPreReqCount = dwPreReqCount; + +cleanup: + if(pRoleHandle) + { + pmd_rolemgmt_plugin_close(pModule, pRoleHandle); + } + return dwError; + +error: + if(ppPreReqs) + { + *ppPreReqs = NULL; + } + if(pdwPreReqCount) + { + *pdwPreReqCount = 0; + } + goto cleanup; +} + +uint32_t +rolemgmt_task_progress_cb( + const char *pszTaskUUID, + const char *pszProgress + ) +{ + uint32_t dwError = 0; + PPMD_PLUGIN_TASK pTask = NULL; + PPMD_PLUGIN_TASK_LOG pLog = NULL; + + if(IsNullOrEmptyString(pszTaskUUID) || IsNullOrEmptyString(pszProgress)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + fprintf(stdout, "Task(%s): %s\n", pszTaskUUID, pszProgress); + + dwError = rolemgmt_find_task_by_id(pszTaskUUID, &pTask); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateMemory(sizeof(PMD_PLUGIN_TASK_LOG), (void **)&pLog); + BAIL_ON_PMD_ERROR(dwError); + + pLog->tStamp = time(NULL); + + dwError = PMDAllocateString(pszProgress, &pLog->pszLog); + BAIL_ON_PMD_ERROR(dwError); + + if(!pTask->pLogData) + { + pTask->pLogData = pLog; + } + else + { + PPMD_PLUGIN_TASK_LOG pTemp = pTask->pLogData; + while(pTemp->pNext) pTemp = pTemp->pNext; + pTemp->pNext = pLog; + } +cleanup: + return dwError; + +error: + fprintf(stderr, "Callback from plugin caused an error: %d\n", dwError); + + rolemgmt_free_plugin_task_logs(pLog); + goto cleanup; +} + +uint32_t +pmd_rolemgmt_role_create_task( + PPMD_PLUGIN_MODULE pModule, + PMD_ROLE_OPERATION nOperation, + const char *pszConfigJson, + PPMD_PLUGIN_TASK *ppTask + ) +{ + uint32_t dwError = 0; + int nLocked = 0; + PPMD_PLUGIN_TASK pTask = NULL; + uuid_t uuidTask = {0}; + + if(!pModule || IsNullOrEmptyString(pszConfigJson) || !ppTask) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if(pModule->pCurrentTask) + { + dwError = ERROR_PMD_ROLE_PLUGIN_HAS_TASKS; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateMemory(sizeof(PMD_PLUGIN_TASK), (void **)&pTask); + BAIL_ON_PMD_ERROR(dwError); + + pTask->tStart = time(NULL); + pTask->pFnProgressCallback = rolemgmt_task_progress_cb; + pTask->nOperation = nOperation; + + dwError = PMDAllocateString(pszConfigJson, &pTask->pszConfigJson); + BAIL_ON_PMD_ERROR(dwError); + + //make uuid for this task + uuid_generate(uuidTask); + + dwError = PMDAllocateMemory(sizeof(char) * UUID_STR_LEN, + (void **)&pTask->pszTaskUUID); + BAIL_ON_PMD_ERROR(dwError); + + dwError = pmd_rolemgmt_plugin_open(pModule, &pTask->pRoleHandle); + BAIL_ON_PMD_ERROR(dwError); + + uuid_unparse(uuidTask, pTask->pszTaskUUID); + + pModule->pCurrentTask = pTask; + *ppTask = pTask; + +cleanup: + return dwError; + +error: + if(ppTask) + { + *ppTask = 0; + } + rolemgmt_free_plugin_module_task(pModule); + goto cleanup; +} + +uint32_t +rolemgmt_archive_current_task( + PPMD_PLUGIN_MODULE pModule + ) +{ + uint32_t dwError = 0; + PPMD_PLUGIN_TASK pTask = NULL; + if(!pModule || !pModule->pCurrentTask) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + pTask = pModule->pCurrentTask; + pModule->pCurrentTask = NULL; + + pTask->pNext = pModule->pTaskHistory; + pModule->pTaskHistory = pTask; + + fprintf(stdout, "Archiving task %s\n", pTask->pszTaskUUID); +error: + return dwError; +} + +void * +pmd_rolemgmt_task_thread( + void *pThreadInfo + ) +{ + uint32_t dwError = 0; + PPMD_PLUGIN_TASK_THREAD_INFO pTaskThreadInfo = pThreadInfo; + if(!pTaskThreadInfo || + !pTaskThreadInfo->pModule || + !pTaskThreadInfo->pTask) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + pTaskThreadInfo->pTask->nStatus = ROLE_STATUS_IN_PROGRESS; + dwError = pmd_rolemgmt_plugin_alter( + pTaskThreadInfo->pModule, + pTaskThreadInfo->pTask); + BAIL_ON_PMD_ERROR(dwError); + + pTaskThreadInfo->pTask->nStatus = ROLE_STATUS_SUCCESS; +cleanup: + if(pTaskThreadInfo) + { + rolemgmt_archive_current_task(pTaskThreadInfo->pModule); + PMDFreeMemory(pTaskThreadInfo); + } + + return NULL; + +error: + if(pTaskThreadInfo) + { + pTaskThreadInfo->pTask->nStatus = ROLE_STATUS_FAILURE; + pTaskThreadInfo->pTask->dwError = dwError; + } + goto cleanup; +} + +uint32_t +pmd_rolemgmt_role_alter( + const char *pszName, + PMD_ROLE_OPERATION nOperation, + const char *pszConfigJson, + char **ppszTaskUUID + ) +{ + uint32_t dwError = 0; + PPMD_PLUGIN_MODULE pModule = NULL; + PPMD_PLUGIN_TASK pTask = NULL; + char *pszTaskUUID = NULL; + int nLocked = 0; + PPMD_PLUGIN_TASK_THREAD_INFO pTaskThreadInfo = NULL; + + if(IsNullOrEmptyString(pszName) || + IsNullOrEmptyString(pszConfigJson) || + !ppszTaskUUID) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = pmd_rolemgmt_get_role_plugin(pszName, &pModule); + BAIL_ON_PMD_ERROR(dwError); + + pthread_mutex_lock(&pModule->mutexTasks); + nLocked = 1; + + dwError = pmd_rolemgmt_role_create_task( + pModule, + nOperation, + pszConfigJson, + &pTask); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateMemory(sizeof(PMD_PLUGIN_TASK_THREAD_INFO), + (void **)&pTaskThreadInfo); + BAIL_ON_PMD_ERROR(dwError); + + pTaskThreadInfo->pModule = pModule; + pTaskThreadInfo->pTask = pTask; + + dwError = pthread_create(&pTask->nThreadID, + NULL, + &pmd_rolemgmt_task_thread, + pTaskThreadInfo); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateString(pTask->pszTaskUUID, &pszTaskUUID); + BAIL_ON_PMD_ERROR(dwError); + + *ppszTaskUUID = pszTaskUUID; +cleanup: + if(nLocked && pModule) + { + pthread_mutex_unlock(&pModule->mutexTasks); + } + return dwError; + +error: + if(ppszTaskUUID) + { + *ppszTaskUUID = NULL; + } + PMD_SAFE_FREE_MEMORY(pszTaskUUID); + //TODO: safely remove this task + //pmd_rolemgmt_role_remove_task(pTask); + goto cleanup; +} + +uint32_t +rolemgmt_find_archived_task_by_id( + const char *pszTaskUUID, + PPMD_PLUGIN_TASK *ppTask +) +{ + uint32_t dwError = 0; + PPMD_PLUGIN_TASK pTask = NULL; + PPMD_PLUGIN_CONTEXT pContext = NULL; + + if(IsNullOrEmptyString(pszTaskUUID) || !ppTask) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + for(pContext = gRoleMgmtEnv.pContexts; pContext; pContext = pContext->pNext) + { + PPMD_PLUGIN_TASK pCurrentTask = NULL; + if(!pContext->pModule || !pContext->pModule->pTaskHistory) + { + continue; + } + + pCurrentTask = pContext->pModule->pTaskHistory; + while(pCurrentTask != NULL) + { + if(!strcasecmp(pCurrentTask->pszTaskUUID, pszTaskUUID)) + { + pTask = pCurrentTask; + break; + } + pCurrentTask = pCurrentTask->pNext; + } + } + + if(!pTask) + { + dwError = ERROR_PMD_ROLE_TASK_NO_LOGS; + BAIL_ON_PMD_ERROR(dwError); + } + + *ppTask = pTask; +cleanup: + return dwError; + +error: + if(ppTask) + { + *ppTask = NULL; + } + goto cleanup; +} + +uint32_t +rolemgmt_find_task_by_id( + const char *pszTaskUUID, + PPMD_PLUGIN_TASK *ppTask + ) +{ + uint32_t dwError = 0; + PPMD_PLUGIN_TASK pTask = NULL; + PPMD_PLUGIN_CONTEXT pContext = NULL; + + if(IsNullOrEmptyString(pszTaskUUID) || !ppTask) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + for(pContext = gRoleMgmtEnv.pContexts; pContext; pContext = pContext->pNext) + { + PPMD_PLUGIN_TASK pCurrentTask = NULL; + if(!pContext->pModule || !pContext->pModule->pCurrentTask) + { + continue; + } + pCurrentTask = pContext->pModule->pCurrentTask; + if(!strcasecmp(pCurrentTask->pszTaskUUID, pszTaskUUID)) + { + pTask = pContext->pModule->pCurrentTask; + break; + } + } + + if(!pTask) + { + dwError = ERROR_PMD_ROLE_TASK_NOT_FOUND; + BAIL_ON_PMD_ERROR(dwError); + } + + *ppTask = pTask; + +cleanup: + return dwError; + +error: + if(ppTask) + { + *ppTask = NULL; + } + goto cleanup; +} + +uint32_t +pmd_rolemgmt_get_status( + const char *pszName, + const char *pszTaskUUID, + PMD_ROLE_STATUS *pnStatus + ) +{ + uint32_t dwError = 0; + PPMD_PLUGIN_TASK pTask = NULL; + + if(IsNullOrEmptyString(pszName) || + IsNullOrEmptyString(pszTaskUUID) || + !pnStatus) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = rolemgmt_find_task_by_id(pszTaskUUID, &pTask); + if (dwError != ERROR_PMD_ROLE_TASK_NOT_FOUND) + { + BAIL_ON_PMD_ERROR(dwError); + } + else + { + dwError = rolemgmt_find_archived_task_by_id(pszTaskUUID, &pTask); + BAIL_ON_PMD_ERROR(dwError); + } + *pnStatus = pTask->nStatus; + +cleanup: + return dwError; + +error: + if(pnStatus) + { + *pnStatus = ROLE_STATUS_NONE; + } + goto cleanup; +} + +uint32_t +pmd_rolemgmt_get_logs( + const char *pszTaskUUID, + uint32_t dwOffset, + uint32_t dwEntriesToFetch, + PPMD_PLUGIN_TASK_LOG *ppTaskLogs + ) +{ + uint32_t dwError = 0; + uint32_t i = 0; + PPMD_PLUGIN_TASK_LOG pTaskLogs = NULL; + PPMD_PLUGIN_TASK pTask = NULL; + + if(IsNullOrEmptyString(pszTaskUUID) || !ppTaskLogs) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = rolemgmt_find_task_by_id(pszTaskUUID, &pTask); + if (dwError != ERROR_PMD_ROLE_TASK_NOT_FOUND) + { + BAIL_ON_PMD_ERROR(dwError); + } + else + { + dwError = rolemgmt_find_archived_task_by_id(pszTaskUUID, &pTask); + BAIL_ON_PMD_ERROR(dwError); + } + + pTaskLogs = pTask->pLogData; + for(i = 0; pTaskLogs && i < dwOffset; ++i, pTaskLogs = pTaskLogs->pNext); + + if(!pTaskLogs) + { + dwError = ERROR_PMD_ROLE_TASK_NO_LOGS; + BAIL_ON_PMD_ERROR(dwError); + } + *ppTaskLogs = pTaskLogs; + +cleanup: + return dwError; + +error: + if(ppTaskLogs) + { + *ppTaskLogs = NULL; + } + goto cleanup; +} + +void +rolemgmt_free_plugin_task_logs( + PPMD_PLUGIN_TASK_LOG pLogs + ) +{ + if(!pLogs) + { + return; + } + while(pLogs) + { + PPMD_PLUGIN_TASK_LOG pNextLog = pLogs->pNext; + PMD_SAFE_FREE_MEMORY(pLogs->pszLog); + PMDFreeMemory(pLogs); + pLogs = pNextLog; + } +} + +void +rolemgmt_free_plugin_module_task( + PPMD_PLUGIN_MODULE pModule + ) +{ + PPMD_PLUGIN_TASK pTask = NULL; + if(!pModule && pModule->pCurrentTask) + { + return; + } + + pTask = pModule->pCurrentTask; + PMD_SAFE_FREE_MEMORY(pTask->pszTaskUUID); + PMD_SAFE_FREE_MEMORY(pTask->pszConfigJson); + if(pTask->pRoleHandle) + { + pmd_rolemgmt_plugin_close(pModule, pTask->pRoleHandle); + } + rolemgmt_free_plugin_task_logs(pTask->pLogData); + PMDFreeMemory(pTask); + pModule->pCurrentTask = NULL; +} + +void +rolemgmt_free_plugin_module_tasks( + PPMD_PLUGIN_MODULE pModule + ) +{ + if(!pModule || !pModule->pCurrentTask) + { + return; + } + pthread_mutex_lock(&pModule->mutexTasks); + + rolemgmt_free_plugin_module_task(pModule); + + pthread_mutex_unlock(&pModule->mutexTasks); +} + +void +rolemgmt_free_plugin_module( + PPMD_PLUGIN_MODULE pModule + ) +{ + if(!pModule) + { + return; + } + + pthread_mutex_lock(&pModule->mutexModule); + + rolemgmt_free_plugin_module_tasks(pModule); + + if(pModule->pFnUnload) + { + pModule->pFnUnload(pModule->pInterface); + pModule->pFnUnload = NULL; + } + + if(pModule->pHandle) + { + dlclose(pModule->pHandle); + pModule->pHandle = NULL; + } + + pthread_mutex_unlock(&pModule->mutexModule); + + PMDFreeMemory(pModule); +} + +void +rolemgmt_free_context( + PPMD_PLUGIN_CONTEXT pContext + ) +{ + if(!pContext) + { + return; + } + + rolemgmt_free_plugin_module(pContext->pModule); + PMD_SAFE_FREE_MEMORY(pContext->pszPluginId); + PMD_SAFE_FREE_MEMORY(pContext->pszPluginPath); + PMDFreeMemory(pContext); +} + +void +rolemgmt_free_contexts( + PPMD_PLUGIN_CONTEXT pContexts + ) +{ + if(!pContexts) + { + return; + } + while(pContexts) + { + PPMD_PLUGIN_CONTEXT pContext = pContexts->pNext; + rolemgmt_free_context(pContexts); + pContexts = pContext; + } +} diff --git a/server/rolemgmt/rolemgmt_config.c b/server/rolemgmt/rolemgmt_config.c new file mode 100644 index 0000000..0c2fb27 --- /dev/null +++ b/server/rolemgmt/rolemgmt_config.c @@ -0,0 +1,570 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#include "includes.h" + +uint32_t +rolemgmt_load_roles( + const char *pszRolesDir, + const char *pszPluginsDir, + PPMD_ROLEMGMT_ROLE *ppAllRoles + ) +{ + uint32_t dwError = 0; + PPMD_CONFIG_ITEM pItems = NULL; + PPMD_CONFIG_ITEM pItem = NULL; + PPMD_ROLEMGMT_ROLE *ppRoles = NULL; + PPMD_ROLEMGMT_ROLE pRoles = NULL; + PPMD_ROLEMGMT_ROLE pRole = NULL; + int nRoleCount = 0; + + dwError = rolemgmt_read_roles(pszRolesDir, &pItems); + BAIL_ON_PMD_ERROR(dwError); + + dwError = rolemgmt_copy_roles(pItems, &ppRoles, &nRoleCount); + BAIL_ON_PMD_ERROR(dwError); + + dwError = rolemgmt_move_role_parents(pItems, ppRoles, nRoleCount, &pRoles); + BAIL_ON_PMD_ERROR(dwError); + + for(pRole = pRoles; pRole; pRole = pRole->pNext) + { + dwError = rolemgmt_move_role_children( + pRole, + ppRoles, + nRoleCount); + BAIL_ON_PMD_ERROR(dwError); + } + + print_roles(pRoles); + + *ppAllRoles = pRoles; +cleanup: + PMD_SAFE_FREE_MEMORY(ppRoles); + rolemgmt_free_items(pItems); + return dwError; + +error: + if(ppAllRoles) + { + *ppAllRoles = NULL; + } + rolemgmt_free_roles(pRoles); + goto cleanup; +} + +uint32_t +rolemgmt_move_role_parents( + PPMD_CONFIG_ITEM pItems, + PPMD_ROLEMGMT_ROLE *ppRoleArray, + int nRoleCount, + PPMD_ROLEMGMT_ROLE *ppRoles + ) +{ + uint32_t dwError = 0; + PPMD_ROLEMGMT_ROLE pRoles = NULL; + PPMD_CONFIG_ITEM pItem = NULL; + + if(!pItems || !ppRoleArray || !ppRoles) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + for(pItem = pItems; pItem; pItem = pItem->pNext) + { + PPMD_ROLEMGMT_ROLE pTemp = NULL; + int i = 0; + + if(!IsNullOrEmptyString(pItem->pszParent)) continue; + + for(i = 0; i < nRoleCount; ++i) + { + if(!ppRoleArray[i]) continue; + + if(!strcmp(ppRoleArray[i]->pszName, pItem->pszName)) + { + pTemp = ppRoleArray[i]; + break; + } + } + if(!pTemp) + { + fprintf(stderr, + "Could not move role parent for %s\n", + pItem->pszName); + dwError = ERROR_PMD_ROLE_CONFIG_NO_PARENT; + BAIL_ON_PMD_ERROR(dwError); + } + pTemp->pNext = pRoles; + pRoles = pTemp; + ppRoleArray[i] = NULL; + } + + *ppRoles = pRoles; + +cleanup: + return dwError; + +error: + goto cleanup; +} + +uint32_t +rolemgmt_get_children_of( + const char *pszParent, + PPMD_ROLEMGMT_ROLE *ppRoles, + int nRoleCount, + PPMD_ROLEMGMT_ROLE **pppChildren, + int *pnChildCount + ) +{ + uint32_t dwError = 0; + PPMD_ROLEMGMT_ROLE *ppChildren = NULL; + int nChildCount = 0; + int i = 0; + + if(IsNullOrEmptyString(pszParent) || + !ppRoles|| + !pppChildren || + !pnChildCount) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + for(i = 0; i < nRoleCount; ++i) + { + if(!ppRoles[i]) continue; + if(!strcmp(pszParent, ppRoles[i]->pszParent)) + { + ++nChildCount; + } + } + + if(nChildCount > 0) + { + int j = 0; + dwError = PMDAllocateMemory(sizeof(PPMD_ROLEMGMT_ROLE) * nChildCount, + (void **)&ppChildren); + BAIL_ON_PMD_ERROR(dwError); + + for(i = 0; i < nRoleCount; ++i) + { + if(!ppRoles[i]) continue; + if(!strcmp(pszParent, ppRoles[i]->pszParent)) + { + ppChildren[j++] = ppRoles[i]; + ppRoles[i] = NULL; + } + } + } + + *pppChildren = ppChildren; + *pnChildCount = nChildCount; + +cleanup: + return dwError; + +error: + if(pppChildren) + { + *pppChildren = ppChildren; + } + if(pnChildCount) + { + *pnChildCount = 0; + } + goto cleanup; +} + + +uint32_t +rolemgmt_move_role_children( + PPMD_ROLEMGMT_ROLE pRole, + PPMD_ROLEMGMT_ROLE *ppRoleArray, + int nRoleCount + ) +{ + uint32_t dwError = 0; + PPMD_ROLEMGMT_ROLE pRoles = NULL; + PPMD_ROLEMGMT_ROLE *ppChildren = NULL; + int i = 0; + + if(!pRole || !ppRoleArray) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = rolemgmt_get_children_of( + pRole->pszId, + ppRoleArray, + nRoleCount, + &pRole->ppChildren, + &pRole->nChildCount); + BAIL_ON_PMD_ERROR(dwError); + + for(i = 0; i < pRole->nChildCount; ++i) + { + dwError = rolemgmt_move_role_children( + pRole->ppChildren[i], + ppRoleArray, + nRoleCount); + BAIL_ON_PMD_ERROR(dwError); + } + +cleanup: + return dwError; + +error: + goto cleanup; +} + +uint32_t +rolemgmt_copy_roles( + PPMD_CONFIG_ITEM pItems, + PPMD_ROLEMGMT_ROLE **pppRoles, + int *pnRoleCount + ) +{ + uint32_t dwError = 0; + PPMD_CONFIG_ITEM pItem = NULL; + PPMD_ROLEMGMT_ROLE *ppRoles = NULL; + int nRoleCount = 0; + int i = 0; + + for(pItem = pItems; pItem; pItem = pItem->pNext) ++nRoleCount; + + dwError = PMDAllocateMemory(sizeof(PPMD_ROLEMGMT_ROLE) * nRoleCount, + (void **)&ppRoles); + BAIL_ON_PMD_ERROR(dwError); + + for(pItem = pItems, i = 0; pItem; pItem = pItem->pNext, ++i) + { + PPMD_ROLEMGMT_ROLE pRole = NULL; + + dwError = PMDAllocateMemory(sizeof(PMD_ROLEMGMT_ROLE), (void **)&ppRoles[i]); + BAIL_ON_PMD_ERROR(dwError); + + pRole = ppRoles[i]; + + dwError = PMDAllocateString(pItem->pszId, &pRole->pszId); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateString(pItem->pszName, &pRole->pszName); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDSafeAllocateString(pItem->pszParent, &pRole->pszParent); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDSafeAllocateString(pItem->pszDisplayName, &pRole->pszDisplayName); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDSafeAllocateString(pItem->pszDescription, &pRole->pszDescription); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDSafeAllocateString(pItem->pszPlugin, &pRole->pszPlugin); + BAIL_ON_PMD_ERROR(dwError); + } + + *pppRoles = ppRoles; + *pnRoleCount = nRoleCount; + +cleanup: + return dwError; + +error: + if(pppRoles) + { + *pppRoles = NULL; + } + if(pnRoleCount) + { + *pnRoleCount = 0; + } + for(i = 0; i < nRoleCount; ++i) + { + rolemgmt_free_roles(ppRoles[i]); + } + PMD_SAFE_FREE_MEMORY(ppRoles); + goto cleanup; +} + +uint32_t +rolemgmt_read_roles( + const char *pszRolesDir, + PPMD_CONFIG_ITEM *ppItemsAll + ) +{ + DIR *pDir = NULL; + struct dirent *pEnt = NULL; + int nLen = 0; + int nLenExt = 0; + PPMD_CONFIG_ITEM pItemsAll = NULL; + char *pszRoleFile = NULL; + uint32_t dwError = 0; + + pDir = opendir(pszRolesDir); + if(pDir == NULL) + { + dwError = ERROR_PMD_ROLES_DIR_OPEN; + BAIL_ON_PMD_ERROR(dwError); + } + + while ((pEnt = readdir (pDir)) != NULL ) + { + PPMD_CONFIG_ITEM pItems = NULL; + PPMD_CONFIG_ITEM pItemsTail = NULL; + + nLen = strlen(pEnt->d_name); + if (nLen <= PMD_ROLE_EXT_LEN || + strcmp(pEnt->d_name + nLen - PMD_ROLE_EXT_LEN, PMD_ROLE_EXT)) + { + continue; + } + + dwError = PMDAllocateStringPrintf( + &pszRoleFile, + "%s/%s", + pszRolesDir, + pEnt->d_name); + BAIL_ON_PMD_ERROR(dwError); + + dwError = rolemgmt_read_role(pszRoleFile, &pItems); + BAIL_ON_PMD_ERROR(dwError); + + PMD_SAFE_FREE_MEMORY(pszRoleFile); + pszRoleFile = NULL; + + pItemsTail = pItems; + if(pItems) + { + while(pItems->pNext) pItems = pItems->pNext; + pItems->pNext = pItemsAll; + pItemsAll = pItemsTail; + pItems = NULL; + } + } + + if(!pItemsAll) + { + dwError = ERROR_PMD_NO_DATA; + BAIL_ON_PMD_ERROR(dwError); + } + + *ppItemsAll = pItemsAll; +cleanup: + if(pDir) + { + closedir(pDir); + } + PMD_SAFE_FREE_MEMORY(pszRoleFile); + return dwError; + +error: + if(ppItemsAll) + { + *ppItemsAll = NULL; + } + rolemgmt_free_items(pItemsAll); + goto cleanup; +} + +uint32_t +rolemgmt_read_role( + const char *pszRoleFile, + PPMD_CONFIG_ITEM *ppItems + ) +{ + uint32_t dwError = 0; + PCONF_DATA pData = NULL; + PCONF_SECTION pSection = NULL; + PPMD_CONFIG_ITEM pItems = NULL; + PPMD_CONFIG_ITEM pItem = NULL; + + if(IsNullOrEmptyString(pszRoleFile) || !ppItems) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = read_config_file(pszRoleFile, + MAX_CONFIG_LINE_LENGTH, + &pData); + BAIL_ON_PMD_ERROR(dwError); + + for(pSection = pData->pSections; pSection; pSection = pSection->pNext) + { + dwError = PMDAllocateMemory(sizeof(PMD_CONFIG_ITEM), + (void **)&pItem); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateString(pSection->pszName, &pItem->pszId); + BAIL_ON_PMD_ERROR(dwError); + + dwError = rolemgmt_load_item_data(pItem, pSection); + BAIL_ON_PMD_ERROR(dwError); + + pItem->pNext = pItems; + pItems = pItem; + pItem = NULL; + } + + *ppItems = pItems; + +cleanup: + free_config_data(pData); + return dwError; + +error: + if(ppItems) + { + *ppItems = NULL; + } + rolemgmt_free_items(pItems); + rolemgmt_free_item(pItem); + goto cleanup; +} + +uint32_t +rolemgmt_load_item_data( + PPMD_CONFIG_ITEM pItem, + PCONF_SECTION pSection + ) +{ + uint32_t dwError = 0; + PKEYVALUE pKV = NULL; + + if(!pItem|| !pSection) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + for(pKV = pSection->pKeyValues; pKV; pKV = pKV->pNext) + { + if(!strcmp(pKV->pszKey, ROLE_CONF_NAME)) + { + dwError = PMDAllocateString(pKV->pszValue, &pItem->pszName); + BAIL_ON_PMD_ERROR(dwError); + } + if(!strcmp(pKV->pszKey, ROLE_CONF_DISPLAY_NAME)) + { + dwError = PMDAllocateString(pKV->pszValue, &pItem->pszDisplayName); + BAIL_ON_PMD_ERROR(dwError); + } + else if(!strcmp(pKV->pszKey, ROLE_CONF_DESCRIPTION)) + { + dwError = PMDAllocateString(pKV->pszValue, &pItem->pszDescription); + BAIL_ON_PMD_ERROR(dwError); + } + else if(!strcmp(pKV->pszKey, ROLE_CONF_PARENT)) + { + dwError = PMDAllocateString(pKV->pszValue, &pItem->pszParent); + BAIL_ON_PMD_ERROR(dwError); + } + else if(!strcmp(pKV->pszKey, ROLE_CONF_PLUGIN)) + { + dwError = PMDAllocateString(pKV->pszValue, &pItem->pszPlugin); + BAIL_ON_PMD_ERROR(dwError); + } + } + +cleanup: + return dwError; + +error: + goto cleanup; +} + +void +print_role_children( + PPMD_ROLEMGMT_ROLE pRole, + int nLevel + ) +{ + int i = 0; + if(!pRole) return; + + for(i = 0; i < pRole->nChildCount; ++i) + { + printf("%*c", nLevel * 2, ' '); + printf("child = %s(%d)\n", pRole->ppChildren[i]->pszName, pRole->nChildCount); + print_role_children(pRole->ppChildren[i], nLevel+1); + } +} + +void +print_roles( + PPMD_ROLEMGMT_ROLE pRoles + ) +{ + if(!pRoles) return; + while(pRoles) + { + int i = 0; + fprintf(stdout, "Name = %s (%d)\n", pRoles->pszName, pRoles->nChildCount); + print_role_children(pRoles, 1); + pRoles = pRoles->pNext; + } +} + +void +print_items( + PPMD_CONFIG_ITEM pItems + ) +{ + if(!pItems) return; + while(pItems) + { + fprintf(stdout, "Name = %s\n", pItems->pszName); + pItems = pItems->pNext; + } +} + +void +rolemgmt_free_item( + PPMD_CONFIG_ITEM pItem + ) +{ + if(!pItem) + { + return; + } + PMD_SAFE_FREE_MEMORY(pItem->pszName); + PMD_SAFE_FREE_MEMORY(pItem->pszDisplayName); + PMD_SAFE_FREE_MEMORY(pItem->pszDescription); + PMD_SAFE_FREE_MEMORY(pItem->pszParent); + PMD_SAFE_FREE_MEMORY(pItem->pszPlugin); + PMDFreeMemory(pItem); +} + +void +rolemgmt_free_items( + PPMD_CONFIG_ITEM pItems + ) +{ + PPMD_CONFIG_ITEM pItem = NULL; + if(!pItems) + { + return; + } + while(pItems) + { + pItem = pItems->pNext; + rolemgmt_free_item(pItems); + pItems = pItem; + } +} diff --git a/server/rolemgmt/rolemgmt_global.c b/server/rolemgmt/rolemgmt_global.c new file mode 100644 index 0000000..e6afda3 --- /dev/null +++ b/server/rolemgmt/rolemgmt_global.c @@ -0,0 +1,17 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#include "includes.h" + +PMD_ROLEMGMT_ENV gRoleMgmtEnv = {0}; diff --git a/server/rolemgmt/rolemgmt_global.h b/server/rolemgmt/rolemgmt_global.h new file mode 100644 index 0000000..92f8bdf --- /dev/null +++ b/server/rolemgmt/rolemgmt_global.h @@ -0,0 +1,17 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#pragma once + +extern PMD_ROLEMGMT_ENV gRoleMgmtEnv; diff --git a/server/rolemgmt/rolemgmt_plugin.c b/server/rolemgmt/rolemgmt_plugin.c new file mode 100644 index 0000000..fc54121 --- /dev/null +++ b/server/rolemgmt/rolemgmt_plugin.c @@ -0,0 +1,227 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#include "includes.h" + +uint32_t +pmd_rolemgmt_plugin_get_version( + const PPMD_PLUGIN_MODULE pModule, + char **ppszVersion + ) +{ + uint32_t dwError = 0; + char *pszVersion = NULL; + + if(!pModule || !ppszVersion) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if(pModule->nDisabled) + { + dwError = ERROR_PMD_ROLE_PLUGIN_DISABLED; + BAIL_ON_PMD_ERROR(dwError); + } + + if(!pModule->pInterface || !pModule->pInterface->pFnRoleVersion) + { + dwError = ERROR_PMD_ROLE_UNMAPPED_FN; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = pModule->pInterface->pFnRoleVersion(&pszVersion); + BAIL_ON_PMD_ERROR(dwError); + + *ppszVersion = pszVersion; +cleanup: + return dwError; + +error: + if(ppszVersion) + { + *ppszVersion = NULL; + } + goto cleanup; +} + +uint32_t +pmd_rolemgmt_plugin_open( + const PPMD_PLUGIN_MODULE pModule, + PPMD_ROLE_HANDLE *ppRoleHandle + ) +{ + uint32_t dwError = 0; + PPMD_ROLE_HANDLE pRoleHandle = NULL; + if(!pModule || !ppRoleHandle) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if(pModule->nDisabled) + { + dwError = ERROR_PMD_ROLE_PLUGIN_DISABLED; + BAIL_ON_PMD_ERROR(dwError); + } + + if(!pModule->pInterface || !pModule->pInterface->pFnRoleOpen) + { + dwError = ERROR_PMD_ROLE_UNMAPPED_FN; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = pModule->pInterface->pFnRoleOpen(&pRoleHandle); + BAIL_ON_PMD_ERROR(dwError); + + *ppRoleHandle = pRoleHandle; + +cleanup: + return dwError; + +error: + if(ppRoleHandle) + { + *ppRoleHandle = NULL; + } + goto cleanup; +} + +uint32_t +pmd_rolemgmt_plugin_close( + const PPMD_PLUGIN_MODULE pModule, + PPMD_ROLE_HANDLE pRoleHandle + ) +{ + uint32_t dwError = 0; + if(!pModule || !pRoleHandle) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if(!pModule->pInterface || !pModule->pInterface->pFnRoleClose) + { + dwError = ERROR_PMD_ROLE_UNMAPPED_FN; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = pModule->pInterface->pFnRoleClose(pRoleHandle); + BAIL_ON_PMD_ERROR(dwError); + +cleanup: + return dwError; + +error: + goto cleanup; +} + +uint32_t +pmd_rolemgmt_plugin_get_prereqs( + const PPMD_PLUGIN_MODULE pModule, + PMD_ROLE_OPERATION nOperation, + const PPMD_ROLE_HANDLE pRoleHandle, + PPMD_ROLE_PREREQ *ppPreReqs, + uint32_t *pdwPreReqCount + ) +{ + uint32_t dwError = 0; + PPMD_ROLE_PREREQ pPreReqs = NULL; + uint32_t dwPreReqCount = 0; + + if(!pModule || !pRoleHandle || !ppPreReqs || !pdwPreReqCount) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if(pModule->nDisabled) + { + dwError = ERROR_PMD_ROLE_PLUGIN_DISABLED; + BAIL_ON_PMD_ERROR(dwError); + } + + if(!pModule->pInterface || !pModule->pInterface->pFnRoleGetPreReqs) + { + dwError = ERROR_PMD_ROLE_UNMAPPED_FN; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = pModule->pInterface->pFnRoleGetPreReqs( + pRoleHandle, + nOperation, + &pPreReqs, + &dwPreReqCount); + BAIL_ON_PMD_ERROR(dwError); + + *ppPreReqs = pPreReqs; + *pdwPreReqCount = dwPreReqCount; + +cleanup: + return dwError; + +error: + if(ppPreReqs) + { + *ppPreReqs = NULL; + } + if(pdwPreReqCount) + { + *pdwPreReqCount = 0; + } + goto cleanup; +} + +uint32_t +pmd_rolemgmt_plugin_alter( + const PPMD_PLUGIN_MODULE pModule, + const PPMD_PLUGIN_TASK pTask + ) +{ + uint32_t dwError = 0; + + if(!pModule || !pTask) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if(pModule->nDisabled) + { + dwError = ERROR_PMD_ROLE_PLUGIN_DISABLED; + BAIL_ON_PMD_ERROR(dwError); + } + + if(!pModule->pInterface || !pModule->pInterface->pFnRoleAlter) + { + dwError = ERROR_PMD_ROLE_UNMAPPED_FN; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = pModule->pInterface->pFnRoleAlter( + pTask->pRoleHandle, + pTask->nOperation, + pTask->pszConfigJson, + pTask->pszTaskUUID, + pTask->pFnProgressCallback, + NULL + ); + BAIL_ON_PMD_ERROR(dwError); + +cleanup: + return dwError; + +error: + goto cleanup; +} diff --git a/server/rolemgmt/rolemgmt_restapi.c b/server/rolemgmt/rolemgmt_restapi.c new file mode 100644 index 0000000..7f282b5 --- /dev/null +++ b/server/rolemgmt/rolemgmt_restapi.c @@ -0,0 +1,577 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#include "includes.h" + +REST_MODULE _rolemgmt_rest_module[] = +{ + { + "/v1/rolemgmt/version", + { + rolemgmt_rest_get_version, + NULL, + NULL, + NULL + } + }, + { + "/v1/rolemgmt/role/version", + { + rolemgmt_rest_get_roleversion, + NULL, + NULL, + NULL + } + }, + { + "/v1/rolemgmt/roles", + { + rolemgmt_rest_get_roles, + NULL, + NULL, + NULL + } + }, + { + "/v1/rolemgmt/role/status", + { + rolemgmt_rest_get_status, + NULL, + NULL, + NULL + } + }, + { + "/v1/rolemgmt/role/logs", + { + rolemgmt_rest_get_logs, + NULL, + NULL, + NULL + } + }, + { + "/v1/rolemgmt/role/alter", + { + NULL, + rolemgmt_rest_alter_put, + NULL, + rolemgmt_rest_alter_delete, + rolemgmt_rest_alter_patch + } + }, + {0} +}; + +uint32_t +rolemgmt_rest_get_registration( + PREST_MODULE *ppRestModule + ) +{ + uint32_t dwError = 0; + + if(!ppRestModule) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + *ppRestModule = _rolemgmt_rest_module; + +cleanup: + return dwError; + +error: + goto cleanup; +} + +uint32_t +rolemgmt_rest_get_version( + void *pInputJson, + void **ppszOutputJson + ) +{ + uint32_t dwError = 0; + char *pszVersion = NULL; + char *pszOutputJson = NULL; + PKEYVALUE pKeyValue = NULL; + + if(!ppszOutputJson) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = pmd_rolemgmt_get_version(&pszVersion); + BAIL_ON_PMD_ERROR(dwError); + + dwError = make_keyvalue("version", pszVersion, &pKeyValue); + BAIL_ON_PMD_ERROR(dwError); + + dwError = get_json_string(pKeyValue, &pszOutputJson); + BAIL_ON_PMD_ERROR(dwError); + + *ppszOutputJson = pszOutputJson; + +cleanup: + PMD_SAFE_FREE_MEMORY(pszVersion); + if(pKeyValue) + { + free_keyvalue(pKeyValue); + } + return dwError; + +error: + if(ppszOutputJson) + { + *ppszOutputJson = NULL; + } + PMD_SAFE_FREE_MEMORY(pszOutputJson); + goto cleanup; +} + +uint32_t +rolemgmt_rest_get_roleversion( + void *pInputJson, + void **ppszOutputJson + ) +{ + uint32_t dwError = 0; + char *pszName = NULL; + char *pszVersion = NULL; + char *pszOutputJson = NULL; + PKEYVALUE pKeyValue = NULL; + const char *pszInputJson = pInputJson; + json_t *pJson = NULL; + if(!pszInputJson || !ppszOutputJson) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = pmd_rolemgmt_get_version(&pszVersion); + BAIL_ON_PMD_ERROR(dwError); + + dwError = get_json_object_from_string(pszInputJson, &pJson); + BAIL_ON_PMD_ERROR(dwError); + + dwError = json_get_string_value(pJson, "name", &pszName); + + dwError = pmd_rolemgmt_role_version(pszName, &pszVersion); + BAIL_ON_PMD_ERROR(dwError); + + dwError = make_keyvalue("version", pszVersion, &pKeyValue); + BAIL_ON_PMD_ERROR(dwError); + + dwError = get_json_string(pKeyValue, &pszOutputJson); + BAIL_ON_PMD_ERROR(dwError); + + *ppszOutputJson = pszOutputJson; + +cleanup: + PMD_SAFE_FREE_MEMORY(pszVersion); + if(pKeyValue) + { + free_keyvalue(pKeyValue); + } + return dwError; + +error: + if(ppszOutputJson) + { + *ppszOutputJson = NULL; + } + PMD_SAFE_FREE_MEMORY(pszOutputJson); + goto cleanup; +} + +uint32_t +get_tasklogs_json( + int nCount, + PPMD_PLUGIN_TASK_LOG pTaskLogs, + char **ppszJson + ) +{ + uint32_t dwError = 0; + char *pszJson = NULL; + json_t *pRoot = NULL; + int i = 0; + + if(!pTaskLogs || !ppszJson) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + pRoot = json_array(); + if(!pRoot) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + for(; pTaskLogs && i < nCount; pTaskLogs = pTaskLogs->pNext, ++i) + { + json_t *pLogObj = json_object(); + json_object_set_new(pLogObj, "log", json_string(pTaskLogs->pszLog)); + json_array_append_new(pRoot, pLogObj); + } + + pszJson = json_dumps(pRoot, 0); + + *ppszJson = pszJson; + +cleanup: + if(pRoot) + { + json_decref(pRoot); + } + return dwError; + +error: + if(ppszJson) + { + *ppszJson = NULL; + } + PMD_SAFE_FREE_MEMORY(pszJson); + goto cleanup; +} + + +uint32_t +get_roles_json_string( + PPMD_ROLEMGMT_ROLE pRoles, + char **ppszJson + ) +{ + uint32_t dwError = 0; + char *pszJson = NULL; + json_t *pRoot = NULL; + PPMD_ROLEMGMT_ROLE pRole = NULL; + + if(!pRoles || !ppszJson) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + pRoot = json_array(); + if(!pRoot) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + for(pRole = pRoles; pRole; pRole = pRole->pNext) + { + json_t *pRoleObj = json_object(); + json_object_set_new(pRoleObj, "id", json_string(pRole->pszId)); + json_object_set_new(pRoleObj, "name", json_string(pRole->pszName)); + json_object_set_new(pRoleObj, "baseurl", json_string(pRole->pszDescription)); + json_array_append_new(pRoot, pRoleObj); + } + + pszJson = json_dumps(pRoot, 0); + + *ppszJson = pszJson; + +cleanup: + if(pRoot) + { + json_decref(pRoot); + } + return dwError; + +error: + if(ppszJson) + { + *ppszJson = NULL; + } + PMD_SAFE_FREE_MEMORY(pszJson); + goto cleanup; +} + +uint32_t +rolemgmt_rest_get_roles( + void *pInputJson, + void **ppszOutputJson + ) +{ + uint32_t dwError = 0; + char *pszOutputJson = NULL; + int nLocked = 0; + PPMD_ROLEMGMT_ROLE pRoles = NULL; + + if(!ppszOutputJson) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + pthread_mutex_lock(&gRoleMgmtEnv.mutexEnv); + nLocked = 1; + + pRoles = gRoleMgmtEnv.pRoles; + if(!pRoles) + { + dwError = ERROR_PMD_NO_DATA; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = get_roles_json_string(pRoles, &pszOutputJson); + BAIL_ON_PMD_ERROR(dwError); + + *ppszOutputJson = pszOutputJson; + +cleanup: + if(nLocked) + { + pthread_mutex_unlock(&gRoleMgmtEnv.mutexEnv); + } + return dwError; + +error: + if(ppszOutputJson) + { + *ppszOutputJson = NULL; + } + PMD_SAFE_FREE_MEMORY(pszOutputJson); + goto cleanup; +} + +uint32_t +rolemgmt_rest_get_status( + void *pInputJson, + void **ppszOutputJson + ) +{ + uint32_t dwError = 0; + char *pszName = NULL; + char *pszTaskUUID = NULL; + char *pszOutputJson = NULL; + char *pszStatus = NULL; + json_t *pJson = NULL; + PMD_ROLE_STATUS nStatus = ROLE_STATUS_NONE; + PKEYVALUE pKeyValue = NULL; + char *pszInputJson = pInputJson; + + if(IsNullOrEmptyString(pszInputJson) || !ppszOutputJson) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = get_json_object_from_string(pszInputJson, &pJson); + BAIL_ON_PMD_ERROR(dwError); + + dwError = json_get_string_value(pJson, "name", &pszName); + BAIL_ON_PMD_ERROR(dwError); + + dwError = json_get_string_value(pJson, "taskid", &pszTaskUUID); + BAIL_ON_PMD_ERROR(dwError); + + dwError = pmd_rolemgmt_get_status(pszName, pszTaskUUID, &nStatus); + BAIL_ON_PMD_ERROR(dwError); + + dwError = make_keyvalue("status", pszStatus, &pKeyValue); + BAIL_ON_PMD_ERROR(dwError); + + dwError = get_json_string(pKeyValue, &pszOutputJson); + BAIL_ON_PMD_ERROR(dwError); + + *ppszOutputJson = pszOutputJson; + +cleanup: + PMD_SAFE_FREE_MEMORY(pszName); + PMD_SAFE_FREE_MEMORY(pszTaskUUID); + PMD_SAFE_FREE_MEMORY(pszStatus); + free_keyvalue(pKeyValue); + return dwError; + +error: + if(ppszOutputJson) + { + *ppszOutputJson = NULL; + } + PMD_SAFE_FREE_MEMORY(pszOutputJson); + goto cleanup; +} + +uint32_t +rolemgmt_rest_get_logs( + void *pInputJson, + void **ppszOutputJson + ) +{ + uint32_t dwError = 0; + char *pszTaskUUID = NULL; + char *pszOutputJson = NULL; + char *pszStartAt = NULL; + char *pszCount = NULL; + char *pszStatus = NULL; + json_t *pJson = NULL; + char *pszInputJson = pInputJson; + int nStartAt = 0; + int nCount = 0; + PPMD_PLUGIN_TASK_LOG pTaskLogs = NULL; + + if(IsNullOrEmptyString(pszInputJson) || !ppszOutputJson) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = get_json_object_from_string(pszInputJson, &pJson); + BAIL_ON_PMD_ERROR(dwError); + + dwError = json_get_string_value(pJson, "taskid", &pszTaskUUID); + BAIL_ON_PMD_ERROR(dwError); + + dwError = json_get_string_value(pJson, "startat", &pszStartAt); + BAIL_ON_PMD_ERROR(dwError); + + dwError = json_get_string_value(pJson, "count", &pszCount); + BAIL_ON_PMD_ERROR(dwError); + + nStartAt = atoi(pszStartAt); + nCount = atoi(pszCount); + + dwError = pmd_rolemgmt_get_logs( + pszTaskUUID, + nStartAt, + nCount, + &pTaskLogs); + BAIL_ON_PMD_ERROR(dwError); + + dwError = get_tasklogs_json(nCount, pTaskLogs, &pszOutputJson); + BAIL_ON_PMD_ERROR(dwError); + + *ppszOutputJson = pszOutputJson; + +cleanup: + PMD_SAFE_FREE_MEMORY(pszTaskUUID); + PMD_SAFE_FREE_MEMORY(pszStartAt); + PMD_SAFE_FREE_MEMORY(pszCount); + return dwError; + +error: + if(ppszOutputJson) + { + *ppszOutputJson = NULL; + } + PMD_SAFE_FREE_MEMORY(pszOutputJson); + goto cleanup; +} + +uint32_t +rolemgmt_rest_do_alter( + PMD_ROLE_OPERATION nOperation, + void *pInputJson, + void **ppszOutputJson + ) +{ + uint32_t dwError = 0; + char *pszTaskUUID = NULL; + char *pszOutputJson = NULL; + char *pszConfig = NULL; + char *pszName = NULL; + json_t *pJson = NULL; + char *pszInputJson = pInputJson; + PKEYVALUE pKeyValue = NULL; + + if(IsNullOrEmptyString(pszInputJson) || !ppszOutputJson) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = get_json_object_from_string(pszInputJson, &pJson); + BAIL_ON_PMD_ERROR(dwError); + + dwError = json_get_string_value(pJson, "name", &pszName); + BAIL_ON_PMD_ERROR(dwError); + + dwError = json_get_string_value(pJson, "config", &pszConfig); + if(nOperation != ROLE_OPERATION_ENABLE && !pszConfig) + { + dwError = PMDAllocateString("{}", &pszConfig); + } + BAIL_ON_PMD_ERROR(dwError); + + dwError = pmd_rolemgmt_role_alter( + pszName, + nOperation, + pszConfig, + &pszTaskUUID); + BAIL_ON_PMD_ERROR(dwError); + + dwError = make_keyvalue("taskid", pszTaskUUID, &pKeyValue); + BAIL_ON_PMD_ERROR(dwError); + + dwError = get_json_string(pKeyValue, &pszOutputJson); + BAIL_ON_PMD_ERROR(dwError); + + *ppszOutputJson = pszOutputJson; + +cleanup: + free_keyvalue(pKeyValue); + PMD_SAFE_FREE_MEMORY(pszName); + PMD_SAFE_FREE_MEMORY(pszConfig); + PMD_SAFE_FREE_MEMORY(pszTaskUUID); + return dwError; + +error: + if(ppszOutputJson) + { + *ppszOutputJson = NULL; + } + PMD_SAFE_FREE_MEMORY(pszOutputJson); + goto cleanup; +} +uint32_t +rolemgmt_rest_alter_put( + void *pInputJson, + void **ppszOutputJson + ) +{ + return rolemgmt_rest_do_alter( + ROLE_OPERATION_ENABLE, + pInputJson, + ppszOutputJson); +} + +uint32_t +rolemgmt_rest_alter_delete( + void *pInputJson, + void **ppszOutputJson + ) +{ + return rolemgmt_rest_do_alter( + ROLE_OPERATION_REMOVE, + pInputJson, + ppszOutputJson); +} + +uint32_t +rolemgmt_rest_alter_patch( + void *pInputJson, + void **ppszOutputJson + ) +{ + return rolemgmt_rest_do_alter( + ROLE_OPERATION_UPDATE, + pInputJson, + ppszOutputJson); +} + diff --git a/server/rolemgmt/rolemgmt_rpcapi.c b/server/rolemgmt/rolemgmt_rpcapi.c new file mode 100644 index 0000000..bfe8965 --- /dev/null +++ b/server/rolemgmt/rolemgmt_rpcapi.c @@ -0,0 +1,474 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#include "includes.h" + +unsigned32 +rolemgmt_rpc_version( + handle_t hBinding, + wstring_t* ppwszVersion + ) +{ + uint32_t dwError = 0; + char* pszVersion = NULL; + wstring_t pwszVersion = NULL; + + if(!hBinding || !ppwszVersion) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = pmd_rolemgmt_get_version(&pszVersion); + BAIL_ON_PMD_ERROR(dwError); + + if(IsNullOrEmptyString(pszVersion)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDRpcServerAllocateWFromA(pszVersion, &pwszVersion); + BAIL_ON_PMD_ERROR(dwError); + + *ppwszVersion = pwszVersion; + +cleanup: + PMD_SAFE_FREE_MEMORY(pszVersion); + return dwError; + +error: + if(ppwszVersion) + { + *ppwszVersion = NULL; + } + PMD_SAFE_FREE_MEMORY(pwszVersion); + goto cleanup; +} + +unsigned32 +rolemgmt_rpc_get_roles( + handle_t hBinding, + PPMD_RPC_ROLEMGMT_ROLE_ARRAY *ppRpcRoleArray + ) +{ + uint32_t dwError = 0; + PPMD_ROLEMGMT_ROLE pRoleMgmtRole = NULL; + PPMD_ROLEMGMT_ROLE pRole = NULL; + PPMD_RPC_ROLEMGMT_ROLE_ARRAY pRpcRoleArray = NULL; + PPMD_RPC_ROLEMGMT_ROLE pRpcRoles = NULL; + uint32_t dwCount = 0; + int i = 0; + int nLocked = 0; + + if(!hBinding || !ppRpcRoleArray) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + pthread_mutex_lock(&gRoleMgmtEnv.mutexEnv); + nLocked = 1; + + pRoleMgmtRole = gRoleMgmtEnv.pRoles; + if(!pRoleMgmtRole) + { + dwError = ERROR_PMD_NO_DATA; + BAIL_ON_PMD_ERROR(dwError); + } + + for(pRole = pRoleMgmtRole; pRole; pRole = pRole->pNext) + { + ++dwCount; + } + + dwError = PMDRpcServerAllocateMemory( + sizeof(PMD_RPC_ROLEMGMT_ROLE_ARRAY), + (void **)&pRpcRoleArray); + BAIL_ON_PMD_ERROR(dwError); + + pRpcRoleArray->dwCount = dwCount; + + dwError = PMDRpcServerAllocateMemory( + sizeof(PMD_RPC_ROLEMGMT_ROLE) * dwCount, + (void **)&pRpcRoles); + BAIL_ON_PMD_ERROR(dwError); + + for(i = 0, pRole = pRoleMgmtRole; pRole; pRole = pRole->pNext, ++i) + { + dwError = PMDRpcServerAllocateWFromA( + pRole->pszId, + &pRpcRoles[i].pwszId); + BAIL_ON_PMD_ERROR(dwError); + dwError = PMDRpcServerAllocateWFromA( + pRole->pszName, + &pRpcRoles[i].pwszName); + BAIL_ON_PMD_ERROR(dwError); + dwError = PMDRpcServerAllocateWFromA( + pRole->pszDescription, + &pRpcRoles[i].pwszDescription); + BAIL_ON_PMD_ERROR(dwError); + } + + pRpcRoleArray->pRoles = pRpcRoles; + + *ppRpcRoleArray = pRpcRoleArray; + +cleanup: + if(nLocked) + { + pthread_mutex_unlock(&gRoleMgmtEnv.mutexEnv); + } + return dwError; + +error: + if(ppRpcRoleArray) + { + *ppRpcRoleArray = NULL; + } + PMDRpcServerFreeMemory(pRpcRoleArray); + goto cleanup; +} + +unsigned32 +rolemgmt_rpc_role_version( + handle_t hBinding, + wstring_t pwszName, + wstring_t* ppwszVersion + ) +{ + uint32_t dwError = 0; + char* pszVersion = NULL; + char* pszName = NULL; + wstring_t pwszVersion = NULL; + + if(!hBinding || !pwszName || !ppwszVersion) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateStringAFromW(pwszName, &pszName); + BAIL_ON_PMD_ERROR(dwError); + + dwError = pmd_rolemgmt_role_version(pszName, &pszVersion); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDRpcServerAllocateWFromA(pszVersion, &pwszVersion); + BAIL_ON_PMD_ERROR(dwError); + + *ppwszVersion = pwszVersion; + +cleanup: + PMD_SAFE_FREE_MEMORY(pszName); + return dwError; + +error: + if(ppwszVersion) + { + *ppwszVersion = NULL; + } + PMD_SAFE_FREE_MEMORY(pwszVersion); + goto cleanup; +} + +unsigned32 +rolemgmt_rpc_role_get_prereqs( + handle_t hBinding, + wstring_t pwszName, + RPC_ROLE_OPERATION nOperation, + PPMD_RPC_ROLEMGMT_PREREQ_ARRAY *ppPrereqArray + ) +{ + uint32_t dwError = 0; + uint32_t dwPrereqCount = 0; + char *pszName = NULL; + PPMD_ROLE_PREREQ pPrereqs = NULL; + PPMD_RPC_ROLEMGMT_PREREQ_ARRAY pPrereqArray = NULL; + if(!hBinding || !pwszName || !ppPrereqArray) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateStringAFromW(pwszName, &pszName); + BAIL_ON_PMD_ERROR(dwError); + + dwError = pmd_rolemgmt_role_get_prereqs( + pszName, + nOperation, + &pPrereqs, + &dwPrereqCount); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDRpcServerAllocateMemory( + sizeof(PMD_RPC_ROLEMGMT_PREREQ_ARRAY), + (void **)&pPrereqArray); + BAIL_ON_PMD_ERROR(dwError); + + pPrereqArray->dwCount = dwPrereqCount; + + if(dwPrereqCount > 0) + { + uint32_t i = 0; + dwError = PMDRpcServerAllocateMemory( + sizeof(PMD_RPC_ROLEMGMT_PREREQ) * dwPrereqCount, + (void **)&pPrereqArray->pPrereqs); + BAIL_ON_PMD_ERROR(dwError); + + for(i = 0; i < dwPrereqCount; ++i) + { + dwError = PMDRpcServerAllocateWFromA( + pPrereqs[i].pszName, + &pPrereqArray->pPrereqs[i].pwszName); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDRpcServerAllocateWFromA( + pPrereqs[i].pszDescription, + &pPrereqArray->pPrereqs[i].pwszDescription); + BAIL_ON_PMD_ERROR(dwError); + } + } + + *ppPrereqArray = pPrereqArray; + +cleanup: + PMD_SAFE_FREE_MEMORY(pszName); + return dwError; + +error: + if(ppPrereqArray) + { + *ppPrereqArray = NULL; + } + rolemgmt_rpc_role_free_prereq_array(pPrereqArray); + goto cleanup; +} + +unsigned32 +rolemgmt_rpc_role_get_status( + handle_t hBinding, + wstring_t pwszName, + wstring_t pwszTaskUUID, + RPC_ROLE_STATUS *pnStatus + ) +{ + uint32_t dwError = 0; + PMD_ROLE_STATUS nStatus = RPC_ROLE_STATUS_NONE; + char *pszName = NULL; + char *pszTaskUUID = NULL; + if(!hBinding || !pwszName || !pwszTaskUUID || !pnStatus) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateStringAFromW(pwszName, &pszName); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateStringAFromW(pwszTaskUUID, &pszTaskUUID); + BAIL_ON_PMD_ERROR(dwError); + + dwError = pmd_rolemgmt_get_status(pszName, pszTaskUUID, &nStatus); + BAIL_ON_PMD_ERROR(dwError); + + *pnStatus = nStatus; +cleanup: + return dwError; + +error: + if(pnStatus) + { + *pnStatus = RPC_ROLE_STATUS_NONE; + } + goto cleanup; +} + +unsigned32 +rolemgmt_rpc_role_alter( + handle_t hBinding, + wstring_t pwszName, + RPC_ROLE_OPERATION nOperation, + wstring_t pwszConfigJson, + wstring_t* ppwszTaskUUID + ) +{ + uint32_t dwError = 0; + char *pszName = NULL; + char *pszConfigJson = NULL; + wstring_t pwszTaskUUID = NULL; + char *pszTaskUUID = NULL; + + if(!hBinding || !pwszName || !pwszConfigJson || !ppwszTaskUUID) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateStringAFromW(pwszName, &pszName); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDAllocateStringAFromW(pwszConfigJson, &pszConfigJson); + BAIL_ON_PMD_ERROR(dwError); + + dwError = pmd_rolemgmt_role_alter( + pszName, + nOperation, + pszConfigJson, + &pszTaskUUID); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDRpcServerAllocateWFromA(pszTaskUUID, &pwszTaskUUID); + BAIL_ON_PMD_ERROR(dwError); + + *ppwszTaskUUID = pwszTaskUUID; + +cleanup: + PMD_SAFE_FREE_MEMORY(pszName); + return dwError; + +error: + if(ppwszTaskUUID) + { + *ppwszTaskUUID = NULL; + } + if(pwszTaskUUID) + { + PMDRpcServerFreeMemory(pwszTaskUUID); + } + goto cleanup; +} + +unsigned32 +rolemgmt_rpc_role_get_log( + handle_t hBinding, + wstring_t pwszTaskUUID, + unsigned32 nOffset, + unsigned32 nEntriesToFetch, + PPMD_RPC_ROLEMGMT_TASK_LOG_ARRAY *ppTaskLogArray + ) +{ + uint32_t dwError = 0; + char *pszTaskUUID = NULL; + PPMD_RPC_ROLEMGMT_TASK_LOG_ARRAY pTaskLogArray = NULL; + PPMD_PLUGIN_TASK_LOG pTaskLogs = NULL; + PPMD_PLUGIN_TASK_LOG pTemp = NULL; + uint32_t i = 0; + + if(!hBinding || !pwszTaskUUID || !ppTaskLogArray) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + if(nEntriesToFetch == 0) + { + dwError = ERROR_PMD_NOTHING_TO_DO; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDAllocateStringAFromW(pwszTaskUUID, &pszTaskUUID); + BAIL_ON_PMD_ERROR(dwError); + + dwError = pmd_rolemgmt_get_logs(pszTaskUUID, + nOffset, + nEntriesToFetch, + &pTaskLogs); + if (dwError != ERROR_PMD_ROLE_TASK_NO_LOGS) + { + BAIL_ON_PMD_ERROR(dwError); + } + else + { + dwError = 0; + } + + for(pTemp = pTaskLogs, i = 0; + pTemp && i < nEntriesToFetch; + pTemp = pTemp->pNext, ++i); + + if (i > 0) + { + dwError = PMDRpcServerAllocateMemory( + sizeof(PMD_RPC_ROLEMGMT_TASK_LOG_ARRAY), + (void **)&pTaskLogArray); + BAIL_ON_PMD_ERROR(dwError); + + pTaskLogArray->dwCount = i; + + dwError = PMDRpcServerAllocateMemory( + sizeof(PMD_RPC_ROLEMGMT_TASK_LOG) * i, + (void **)&pTaskLogArray->pTaskLogs); + BAIL_ON_PMD_ERROR(dwError); + + for(i = 0, pTemp = pTaskLogs; i < pTaskLogArray->dwCount; ++i) + { + dwError = PMDRpcServerAllocateWFromA( + pTemp->pszLog, + &pTaskLogArray->pTaskLogs[i].pwszLog); + BAIL_ON_PMD_ERROR(dwError); + } + } + + *ppTaskLogArray = pTaskLogArray; +cleanup: + return dwError; + +error: + if(ppTaskLogArray) + { + *ppTaskLogArray = NULL; + } + rolemgmt_rpc_role_free_task_log_array(pTaskLogArray); + goto cleanup; +} + +void +rolemgmt_rpc_role_free_task_log_array( + PPMD_RPC_ROLEMGMT_TASK_LOG_ARRAY pTaskLogArray + ) +{ + uint32_t i = 0; + if(!pTaskLogArray) + { + return; + } + for(i = 0; i < pTaskLogArray->dwCount; ++i) + { + PPMD_RPC_ROLEMGMT_TASK_LOG pTaskLog = &pTaskLogArray->pTaskLogs[i]; + PMD_RPCSRV_SAFE_FREE_MEMORY(pTaskLog->pwszLog); + } + PMD_RPCSRV_SAFE_FREE_MEMORY(pTaskLogArray->pTaskLogs); + PMDRpcServerFreeMemory(pTaskLogArray); +} + +void +rolemgmt_rpc_role_free_prereq_array( + PPMD_RPC_ROLEMGMT_PREREQ_ARRAY pPrereqArray + ) +{ + uint32_t i = 0; + if(!pPrereqArray) + { + return; + } + for(i = 0; i < pPrereqArray->dwCount; ++i) + { + PPMD_RPC_ROLEMGMT_PREREQ pPrereq = &pPrereqArray->pPrereqs[i]; + PMD_RPCSRV_SAFE_FREE_MEMORY(pPrereq->pwszName); + PMD_RPCSRV_SAFE_FREE_MEMORY(pPrereq->pwszDescription); + } + PMD_RPCSRV_SAFE_FREE_MEMORY(pPrereqArray->pPrereqs); + PMDRpcServerFreeMemory(pPrereqArray); +} diff --git a/server/rolemgmt/structs.h b/server/rolemgmt/structs.h new file mode 100644 index 0000000..bf5a814 --- /dev/null +++ b/server/rolemgmt/structs.h @@ -0,0 +1,92 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#pragma once + +typedef struct _PMD_CONFIG_ITEM_ +{ + char *pszId; + char *pszName; + char *pszDisplayName; + char *pszDescription; + char *pszParent; + char *pszPlugin; + struct _PMD_CONFIG_ITEM_ *pNext; +}PMD_CONFIG_ITEM, *PPMD_CONFIG_ITEM; + +typedef struct _PMD_PLUGIN_TASK_LOG_ +{ + time_t tStamp; + char *pszLog; + struct _PMD_PLUGIN_TASK_LOG_ *pNext; +}PMD_PLUGIN_TASK_LOG, *PPMD_PLUGIN_TASK_LOG; + +typedef struct _PMD_PLUGIN_TASK_ +{ + pthread_t nThreadID; + char *pszTaskUUID; + PMD_ROLE_STATUS nStatus; + uint32_t dwError; + time_t tStart; + PPMD_ROLE_HANDLE pRoleHandle; + PMD_ROLE_OPERATION nOperation; + char *pszConfigJson; + PFN_ALTER_PROGRESS_CALLBACK pFnProgressCallback; + PPMD_PLUGIN_TASK_LOG pLogData; + + struct _PMD_PLUGIN_TASK_ *pNext; +}PMD_PLUGIN_TASK, *PPMD_PLUGIN_TASK; + +typedef struct _PMD_PLUGIN_MODULE_ +{ + int nDisabled; + pthread_mutex_t mutexModule; + //dlopen handle + void *pHandle; + + //Tasks + pthread_mutex_t mutexTasks; + PPMD_PLUGIN_TASK pCurrentTask; + PPMD_PLUGIN_TASK pTaskHistory; + + //Mandatory entry point + PFN_PMD_ROLEPLUGIN_LOAD_INTERFACE pFnLoad; + //Optional unload + PFN_PMD_ROLEPLUGIN_UNLOAD_INTERFACE pFnUnload; + + //interface fn table returned by load. + PPMD_ROLE_PLUGIN_INTERFACE pInterface; +}PMD_PLUGIN_MODULE, *PPMD_PLUGIN_MODULE; + +typedef struct _PMD_PLUGIN_TASK_THREAD_INFO_ +{ + PPMD_PLUGIN_MODULE pModule; + PPMD_PLUGIN_TASK pTask; +}PMD_PLUGIN_TASK_THREAD_INFO,*PPMD_PLUGIN_TASK_THREAD_INFO; + +typedef struct _PMD_PLUGIN_CONTEXT_ +{ + char *pszPluginId; + char *pszPluginPath; + PPMD_PLUGIN_MODULE pModule; + + struct _PMD_PLUGIN_CONTEXT_ *pNext; +}PMD_PLUGIN_CONTEXT, *PPMD_PLUGIN_CONTEXT; + +typedef struct _PMD_ROLEMGMT_ENV_ +{ + pthread_mutex_t mutexEnv; + PPMD_PLUGIN_CONTEXT pContexts; + PPMD_ROLEMGMT_ROLE pRoles; +}PMD_ROLEMGMT_ENV, *PPMD_ROLEMGMT_ENV; diff --git a/server/rpmostreeapi.c b/server/rpmostreeapi.c new file mode 100644 index 0000000..6e1adc4 --- /dev/null +++ b/server/rpmostreeapi.c @@ -0,0 +1,201 @@ +/* + * Copyright © 2019 VMware, Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, without + * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + + +#include "includes.h" + +unsigned32 +rpmostree_rpc_version( + handle_t hBinding, + wstring_t* ppwszVersion + ) +{ + uint32_t dwError = 0; + char* pszVersion = NULL; + wstring_t pwszVersion = NULL; + + if(!hBinding || !ppwszVersion) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + pszVersion = PACKAGE_VERSION; + if(IsNullOrEmptyString(pszVersion)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + dwError = PMDRpcServerAllocateWFromA(pszVersion, &pwszVersion); + BAIL_ON_PMD_ERROR(dwError); + + *ppwszVersion = pwszVersion; + +cleanup: + return dwError; + +error: + if(ppwszVersion) + { + *ppwszVersion = NULL; + } + PMD_SAFE_FREE_MEMORY(pwszVersion); + goto cleanup; +} + +unsigned32 +rpmostree_rpc_server_info( + handle_t hBinding, + PPMD_RPMOSTREE_SERVER_INFO* ppInfo + ) +{ + uint32_t dwError = 0; + PPMD_CONFIG pConfig = NULL; + PPMD_RPMOSTREE_SERVER_INFO pInfo = NULL; + + if(!hBinding || !ppInfo) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + CHECK_RPC_ACCESS(hBinding, dwError); + + dwError = pmd_read_config( + PMD_CONFIG_FILE_NAME, + PMD_CONFIG_MAIN_GROUP, + &pConfig); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDRpcServerAllocateMemory( + sizeof(PMD_RPMOSTREE_SERVER_INFO), + (void**)&pInfo); + BAIL_ON_PMD_ERROR(dwError); + + pInfo->dwServerType = pConfig->nServerType; + + dwError = PMDRpcServerAllocateWFromA( + pConfig->pszServerUrl, + &pInfo->pwszServerUrl); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDRpcServerAllocateWFromA( + pConfig->pszCurrentHash, + &pInfo->pwszCurrentHash); + BAIL_ON_PMD_ERROR(dwError); + + *ppInfo = pInfo; + +cleanup: + if(pConfig) + { + pmd_free_config(pConfig); + } + return dwError; + +error: + if(ppInfo) + { + *ppInfo = NULL; + } + goto cleanup; +} + +unsigned32 +rpmostree_rpc_client_info( + handle_t hBinding, + PPMD_RPMOSTREE_CLIENT_INFO* ppInfo + ) +{ + uint32_t dwError = 0; + PPMD_CONFIG pConfig = NULL; + PPMD_RPMOSTREE_CLIENT_INFO pInfo = NULL; + + if(!hBinding || !ppInfo) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + CHECK_RPC_ACCESS(hBinding, dwError); + + dwError = pmd_read_config( + PMD_CONFIG_FILE_NAME, + PMD_CONFIG_MAIN_GROUP, + &pConfig); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDRpcServerAllocateMemory( + sizeof(PMD_RPMOSTREE_CLIENT_INFO), + (void**)&pInfo); + BAIL_ON_PMD_ERROR(dwError); + + pInfo->dwServerType = pConfig->nServerType; + + dwError = PMDRpcServerAllocateWFromA( + pConfig->pszComposeServer, + &pInfo->pwszComposeServer); + BAIL_ON_PMD_ERROR(dwError); + + dwError = PMDRpcServerAllocateWFromA( + pConfig->pszCurrentHash, + &pInfo->pwszCurrentHash); + BAIL_ON_PMD_ERROR(dwError); + + *ppInfo = pInfo; +cleanup: + if(pConfig) + { + pmd_free_config(pConfig); + } + return dwError; + +error: + if(ppInfo) + { + *ppInfo = NULL; + } + goto cleanup; +} + +unsigned32 +rpmostree_rpc_client_syncto( + handle_t hBinding, + wstring_t pwszHash + ) +{ + uint32_t dwError = 0; + char* pszHash = NULL; + + if(!hBinding || !pwszHash) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_PMD_ERROR(dwError); + } + + CHECK_RPC_ACCESS(hBinding, dwError); + + dwError = PMDAllocateStringAFromW(pwszHash, &pszHash); + BAIL_ON_PMD_ERROR(dwError); + + printf("Syncing to hash: %s\n", pszHash); + +cleanup: + PMD_SAFE_FREE_MEMORY(pszHash); + return dwError; + +error: + goto cleanup; +} diff --git a/server/server.c b/server/server.c index de69976..b831224 100644 --- a/server/server.c +++ b/server/server.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" void @@ -64,6 +63,8 @@ start_rpc_server( pkg_v1_0_s_ifspec, pmd_v1_0_s_ifspec, netmgmt_v1_0_s_ifspec, + rolemgmt_v1_0_s_ifspec, + rpmostree_v1_0_s_ifspec, usermgmt_v1_0_s_ifspec }; int nInterfaces = sizeof(interface_spec)/sizeof(*interface_spec); @@ -93,7 +94,7 @@ start_rpc_server( * Register the Interface with the local endpoint mapper (rpcd) */ - printf ("Registering server.... \n"); + fprintf (stdout, "Registering server.... \n"); while(nInterfaces) { rpc_server_register_if(interface_spec[--nInterfaces], @@ -136,14 +137,18 @@ int main(int argc, char *argv[]) } BAIL_ON_PMD_ERROR(dwError); - dwError = init_security_config(gpServerEnv->pConfig->pszApiSecurityConf, - &gpServerEnv->pSecurityContext); + dwError = init_security_config( + gpServerEnv->pConfig->pszApiSecurityConf, + &gpServerEnv->pSecurityContext); + BAIL_ON_PMD_ERROR(dwError); + + dwError = pmd_rolemgmt_load(); BAIL_ON_PMD_ERROR(dwError); dwError = StartRestServer(); if (dwError) { - printf("start_rest_server: failed 0x%x : %d\n", dwError, dwError); + fprintf(stderr, "start_rest_server: failed 0x%x : %d\n", dwError, dwError); BAIL_ON_PMD_ERROR(dwError); } nRestServerStarted = 1; @@ -151,7 +156,7 @@ int main(int argc, char *argv[]) dwError = start_rpc_server(&hRpc); if (dwError) { - printf("start_rpc_server: failed 0x%x : %d\n", dwError, dwError); + fprintf(stderr, "start_rpc_server: failed 0x%x : %d\n", dwError, dwError); BAIL_ON_PMD_ERROR(dwError); } print_endpoints(hRpc); @@ -159,14 +164,14 @@ int main(int argc, char *argv[]) /* * Begin listening for calls */ - printf ("listening for calls....\n"); + fprintf (stdout, "listening for calls....\n"); DCETHREAD_TRY { rpc_server_listen(rpc_c_listen_max_calls_default, &dwError); } DCETHREAD_CATCH_ALL(THIS_CATCH) { - printf ("Server stoppped listening\n"); + fprintf (stdout, "Server stoppped listening\n"); } DCETHREAD_ENDTRY; @@ -179,6 +184,8 @@ int main(int argc, char *argv[]) StopRestServer(); } pmd_free_server_env(gpServerEnv); + pmd_rolemgmt_unload(); + return dwError; diff --git a/server/structs.h b/server/structs.h index 5714bc7..f079c57 100644 --- a/server/structs.h +++ b/server/structs.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #pragma once struct _PMD_SECURITY_CONTEXT_; @@ -31,6 +30,12 @@ typedef struct _PMD_REST_CONFIG_ char *pszLogFile; }PMD_REST_CONFIG, *PPMD_REST_CONFIG; +typedef struct _PMD_ROLES_CONFIG_ +{ + char *pszDir; + char *pszPluginsDir; +}PMD_ROLES_CONFIG, *PPMD_ROLES_CONFIG; + typedef struct _PMD_CONFIG_ { int nServerType; @@ -40,6 +45,7 @@ typedef struct _PMD_CONFIG_ char *pszApiSecurityConf; PPMD_REST_CONFIG pRestConfig; char *pszPrivsepPubKeyFile; + PPMD_ROLES_CONFIG pRolesConfig; }PMD_CONFIG, *PPMD_CONFIG; typedef struct _HPRIVSEP_TO_HPKG_ diff --git a/tools/Makefile.am b/tools/Makefile.am index 73e450e..cde81f8 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,2 +1,6 @@ +CLEANFILES= + SUBDIRS = \ cli + +CLEANFILES += pmd.spec diff --git a/tools/cli/Makefile.am b/tools/cli/Makefile.am index 110df79..1c9b93c 100644 --- a/tools/cli/Makefile.am +++ b/tools/cli/Makefile.am @@ -12,6 +12,7 @@ SUBDIRS = \ fwmgmt \ pkgmgmt \ netmgmt \ + rolemgmt \ usermgmt if ENABLE_DEMO @@ -24,6 +25,7 @@ pmd_cli_LDADD = \ $(top_builddir)/tools/cli/fwmgmt/libfwmgmtcli.la \ $(top_builddir)/tools/cli/pkgmgmt/libpkgmgmtcli.la \ $(top_builddir)/tools/cli/netmgmt/libnetmgmtcli.la \ + $(top_builddir)/tools/cli/rolemgmt/librolemgmtcli.la \ $(top_builddir)/tools/cli/usermgmt/libusermgmtcli.la if ENABLE_DEMO pmd_cli_LDADD += $(top_builddir)/tools/cli/demo/libdemocli.la diff --git a/tools/cli/defines.h b/tools/cli/defines.h index 77f30ad..e279c98 100644 --- a/tools/cli/defines.h +++ b/tools/cli/defines.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -28,6 +28,7 @@ #define ERROR_PMD_CLI_OPTION_ARG_UNEXPECTED (ERROR_PMD_CLI_BASE + 11) #define ERROR_PMD_CLI_SERVER_NAME_REQUIRED (ERROR_PMD_CLI_BASE + 12) #define ERROR_PMD_CLI_SYNCTO_REQUIRED (ERROR_PMD_CLI_BASE + 13) +#define ERROR_PMD_CLI_NO_SUCH_OPTION (ERROR_PMD_CLI_BASE + 14) //main cli options #define OPT_SERVERNAME "servername" @@ -76,4 +77,5 @@ {ERROR_PMD_CLI_PROVIDES_EXPECT_ARG, "ERROR_PMD_CLI_PROVIDES_EXPECT_ARG", "Need an item to match"}, \ {ERROR_PMD_CLI_SERVER_NAME_REQUIRED, "ERROR_PMD_CLI_SERVER_NAME_REQUIRED", "Server name or ip address must be specified. Please specify using --server."}, \ {ERROR_PMD_CLI_SYNCTO_REQUIRED, "ERROR_PMD_CLI_SYNCTO_REQUIRED", "Please specify a hash to sync to."}, \ + {ERROR_PMD_CLI_NO_SUCH_OPTION, "ERROR_PMD_CLI_NO_SUCH_OPTION", "Specified option is invalid."}, \ }; diff --git a/tools/cli/main.c b/tools/cli/main.c index cab4274..3c8d3db 100644 --- a/tools/cli/main.c +++ b/tools/cli/main.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" //Does command dispatch @@ -64,6 +63,7 @@ route_cmd( {"firewall", "firewall management", fwmgmt_main}, {"net", "network management", netmgr_main}, {"pkg", "package management", pkg_main}, + {"rolemgmt", "role management", rolemgmt_main}, {"usr", "user management", usermgmt_main}, {NULL, NULL, NULL} }; @@ -121,6 +121,7 @@ route_cmd( { ShowRegisteredComponents(arKnownComps); show_usage(); + dwError = 0; } if(dwError == ESRCH) { diff --git a/tools/cli/pkgmgmt/includes.h b/tools/cli/pkgmgmt/includes.h index 269205e..1c39cc9 100644 --- a/tools/cli/pkgmgmt/includes.h +++ b/tools/cli/pkgmgmt/includes.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -8,10 +8,9 @@ * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, without * warranties or conditions of any kind, EITHER EXPRESS OR IMPLIED. See the - * License for the specific language governing permissions and limitations + * License for the specific language governing permissions and limitations * under the License. - */ - +*/ #pragma once #include diff --git a/tools/cli/pkgmgmt/pkg_main.c b/tools/cli/pkgmgmt/pkg_main.c index 78d3d99..e490683 100644 --- a/tools/cli/pkgmgmt/pkg_main.c +++ b/tools/cli/pkgmgmt/pkg_main.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" uint32_t diff --git a/tools/cli/prototypes.h b/tools/cli/prototypes.h index ed01076..9347934 100644 --- a/tools/cli/prototypes.h +++ b/tools/cli/prototypes.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -11,8 +11,6 @@ * License for the specific language governing permissions and limitations * under the License. */ - - #pragma once //component main functions @@ -172,6 +170,7 @@ free_cmd_args( ); //utils.c + int PMDIsSystemError( uint32_t dwError diff --git a/tools/cli/rolemgmt/includes.h b/tools/cli/rolemgmt/includes.h index f27f218..9b5f170 100644 --- a/tools/cli/rolemgmt/includes.h +++ b/tools/cli/rolemgmt/includes.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,14 +12,15 @@ * under the License. */ - #pragma once #include #include +#include #include "../includes.h" #include +#include #include "structs.h" #include "prototypes.h" diff --git a/tools/cli/rolemgmt/prototypes.h b/tools/cli/rolemgmt/prototypes.h index 61ab67d..fb9ddc1 100644 --- a/tools/cli/rolemgmt/prototypes.h +++ b/tools/cli/rolemgmt/prototypes.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #pragma once //rolemgmt_main.c @@ -34,6 +33,37 @@ rolemgmt_cli_get_roles_cmd( PROLEMGMT_CMD_ARGS pCmdArgs ); +uint32_t +rolemgmt_cli_get_logs_cmd( + PPMDHANDLE hPMD, + PROLEMGMT_CMD_ARGS pCmdArgs + ); + +uint32_t +rolemgmt_cli_get_version_cmd( + PPMDHANDLE hPMD, + PROLEMGMT_CMD_ARGS pCmdArgs + ); + +uint32_t +rolemgmt_cli_get_prereqs_cmd( + PPMDHANDLE hPMD, + PROLEMGMT_CMD_ARGS pCmdArgs + ); + +uint32_t +rolemgmt_cli_get_status_cmd( + PPMDHANDLE hPMD, + PROLEMGMT_CMD_ARGS pCmdArgs + ); + +uint32_t +rolemgmt_cli_alter_cmd( + PPMDHANDLE hPMD, + PROLEMGMT_CMD_ARGS pCmdArgs, + PMD_ROLE_OPERATION nOperation + ); + void rolemgmt_cli_show_help( ); @@ -54,8 +84,6 @@ rolemgmt_options_error( uint32_t rolemgmt_validate_options( - const char *pszName, - const char *pszArg, PROLEMGMT_CMD_ARGS pCmdArgs ); @@ -70,3 +98,9 @@ void rolemgmt_free_cmd_args( PROLEMGMT_CMD_ARGS pCmdArgs ); + +uint32_t +rolemgmt_status_to_string( + PMD_ROLE_STATUS nStatus, + char **ppszStatus + ); diff --git a/tools/cli/rolemgmt/rolemgmt_help.c b/tools/cli/rolemgmt/rolemgmt_help.c index 882cd39..864daae 100644 --- a/tools/cli/rolemgmt/rolemgmt_help.c +++ b/tools/cli/rolemgmt/rolemgmt_help.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" void @@ -25,7 +24,35 @@ rolemgmt_cli_show_help( printf("List of Main Commands\n"); printf("\n"); - printf("help Display a helpful usage message\n"); printf("roles Show current roles.\n"); printf("version Show version.\n"); + printf("help Display a helpful usage message\n"); + + printf("roles --list (default) Show available roles.\n"); + + printf("roles\n" + " --prereqs\n" + " --name List prerequisites.\n"); + + printf("roles\n" + " --status\n" + " --name \n" + " --taskid Show status of task.\n"); + + printf("roles\n" + " --enable\n" + " --name \n" + " --config Enable role.\n"); + + printf("roles\n" + " --update\n" + " --name \n" + " --config Update role.\n"); + + printf("roles\n" + " --remove\n" + " --name \n" + " --config Remove role.\n"); + + printf("version Show version.\n"); } diff --git a/tools/cli/rolemgmt/rolemgmt_main.c b/tools/cli/rolemgmt/rolemgmt_main.c index 7a1e226..1f56eb7 100644 --- a/tools/cli/rolemgmt/rolemgmt_main.c +++ b/tools/cli/rolemgmt/rolemgmt_main.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" uint32_t @@ -78,7 +77,7 @@ rolemgmt_main( cleanup: if(hPMD) { - PMDFreeHandle(hPMD); + rpc_free_handle(hPMD); } if(pCmdArgs) { @@ -90,6 +89,34 @@ rolemgmt_main( goto cleanup; } +uint32_t +print_task_logs( + PPMD_ROLEMGMT_TASK_LOG pTaskLogs, + uint32_t dwTaskLogCount + ) +{ + uint32_t dwError = 0; + uint32_t i = 0; + + if(!pTaskLogs || dwTaskLogCount == 0) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_CLI_ERROR(dwError); + } + + for(i = 0; i < dwTaskLogCount; ++i) + { + fprintf(stdout, "%s\n", pTaskLogs[i].pszLog); + } + +cleanup: + return dwError; + +error: + goto cleanup; +} + + uint32_t rolemgmt_cli_show_version_cmd( PPMDHANDLE hPMD, @@ -137,12 +164,41 @@ rolemgmt_cli_roles_cmd( dwError = rolemgmt_cli_get_roles_cmd(hPMD, pCmdArgs); BAIL_ON_CLI_ERROR(dwError); break; - case ROLEMGMT_OPERATION_SET: - //dwError = fwmgmt_cli_add_rules_cmd(hPMD, pCmdArgs); + case ROLEMGMT_OPERATION_VERSION: + dwError = rolemgmt_cli_get_version_cmd(hPMD, pCmdArgs); + BAIL_ON_CLI_ERROR(dwError); + break; + case ROLEMGMT_OPERATION_LOGS: + dwError = rolemgmt_cli_get_logs_cmd(hPMD, pCmdArgs); BAIL_ON_CLI_ERROR(dwError); break; - case ROLEMGMT_OPERATION_DELETE: - //dwError = fwmgmt_cli_delete_rules_cmd(hPMD, pCmdArgs); + case ROLEMGMT_OPERATION_PREREQS: + dwError = rolemgmt_cli_get_prereqs_cmd(hPMD, pCmdArgs); + BAIL_ON_CLI_ERROR(dwError); + break; + case ROLEMGMT_OPERATION_STATUS: + dwError = rolemgmt_cli_get_status_cmd(hPMD, pCmdArgs); + BAIL_ON_CLI_ERROR(dwError); + break; + case ROLEMGMT_OPERATION_ENABLE: + dwError = rolemgmt_cli_alter_cmd( + hPMD, + pCmdArgs, + ROLE_OPERATION_ENABLE); + BAIL_ON_CLI_ERROR(dwError); + break; + case ROLEMGMT_OPERATION_REMOVE: + dwError = rolemgmt_cli_alter_cmd( + hPMD, + pCmdArgs, + ROLE_OPERATION_REMOVE); + BAIL_ON_CLI_ERROR(dwError); + break; + case ROLEMGMT_OPERATION_UPDATE: + dwError = rolemgmt_cli_alter_cmd( + hPMD, + pCmdArgs, + ROLE_OPERATION_UPDATE); BAIL_ON_CLI_ERROR(dwError); break; default: @@ -177,12 +233,298 @@ rolemgmt_cli_get_roles_cmd( for(pRole = pRoles; pRole; pRole = pRole->pNext) { fprintf(stdout, "%s\n", pRole->pszRole); + fprintf(stdout, "Id : %s\n", pRole->pszId); + fprintf(stdout, "Name : %s\n", pRole->pszName); + fprintf(stdout, "Description : %s\n", pRole->pszDescription); + fprintf(stdout, "\n"); } cleanup: rolemgmt_free_roles(pRoles); return dwError; +error: + if(dwError == ERROR_PMD_NO_DATA) + { + fprintf(stderr, "There are no roles configured. Role configuration is read from \".role\" files under /etc/javelin.roles.d or from a directory configured under the \"roles\" section in /etc/pmd/pmd.conf.\n"); + } + goto cleanup; +} + +uint32_t +rolemgmt_cli_get_logs_cmd( + PPMDHANDLE hPMD, + PROLEMGMT_CMD_ARGS pCmdArgs + ) +{ + uint32_t dwError = 0; + PPMD_ROLEMGMT_TASK_LOG pTaskLogs = NULL; + uint32_t dwOffset = 0; + uint32_t dwTaskLogCount = 0; + PMD_ROLE_STATUS nStatus = ROLE_STATUS_NONE; + + if(!hPMD || !pCmdArgs || IsNullOrEmptyString(pCmdArgs->pszTaskUUID)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_CLI_ERROR(dwError); + } + + do + { + dwError = rolemgmt_get_log( + hPMD, + pCmdArgs->pszTaskUUID, + dwOffset, + 1, + &pTaskLogs, + &dwTaskLogCount); + + if(dwError == ERROR_PMD_ROLE_TASK_NO_LOGS) + { + dwError = rolemgmt_get_status( + hPMD, + pCmdArgs->pszName, + pCmdArgs->pszTaskUUID, + &nStatus); + BAIL_ON_CLI_ERROR(dwError); + + if(nStatus == ROLE_STATUS_IN_PROGRESS) + { + fprintf(stdout, "Task is in progress. Waiting for more logs..\n"); + dwError = 0; + sleep(1); + continue; + } + } + BAIL_ON_CLI_ERROR(dwError); + + if(pTaskLogs) + { + dwError = print_task_logs(pTaskLogs, dwTaskLogCount); + BAIL_ON_CLI_ERROR(dwError); + } + + //wait a bit + sleep(1); + dwOffset += dwTaskLogCount; + }while(dwTaskLogCount > 0); + +cleanup: + return dwError; + +error: + goto cleanup; +} + + +uint32_t +rolemgmt_cli_get_version_cmd( + PPMDHANDLE hPMD, + PROLEMGMT_CMD_ARGS pCmdArgs + ) +{ + uint32_t dwError = 0; + char *pszVersion = NULL; + + if(!hPMD || !pCmdArgs || IsNullOrEmptyString(pCmdArgs->pszRole)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_CLI_ERROR(dwError); + } + + dwError = rolemgmt_get_role_version(hPMD, pCmdArgs->pszRole, &pszVersion); + BAIL_ON_CLI_ERROR(dwError); + + fprintf(stdout, "Version of %s : %s\n", pCmdArgs->pszRole, pszVersion); + +cleanup: + PMD_SAFE_FREE_MEMORY(pszVersion); + return dwError; + +error: + goto cleanup; +} + +uint32_t +rolemgmt_cli_get_prereqs_cmd( + PPMDHANDLE hPMD, + PROLEMGMT_CMD_ARGS pCmdArgs + ) +{ + uint32_t dwError = 0; + uint32_t dwPrereqCount = 0; + uint32_t i = 0; + char *pszVersion = NULL; + PPMD_ROLE_PREREQ pPrereqs = NULL; + PMD_ROLE_OPERATION nOperation = ROLE_OPERATION_NONE; + + if(!hPMD || !pCmdArgs || IsNullOrEmptyString(pCmdArgs->pszRole)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_CLI_ERROR(dwError); + } + + dwError = rolemgmt_get_prereqs(hPMD, + pCmdArgs->pszRole, + nOperation, + &pPrereqs, + &dwPrereqCount); + BAIL_ON_CLI_ERROR(dwError); + + if(dwPrereqCount == 0) + { + fprintf(stdout, "There are no prereqs for %s\n", pCmdArgs->pszRole); + } + else + { + fprintf(stdout, "Prereqs for %s\n", pCmdArgs->pszRole); + + for(i = 0; i < dwPrereqCount; ++i) + { + fprintf(stdout, " %d. %s - %s\n", + i+1, + pPrereqs[i].pszName, + pPrereqs[i].pszDescription); + } + } +cleanup: + return dwError; + +error: + goto cleanup; +} + +uint32_t +rolemgmt_cli_get_status_cmd( + PPMDHANDLE hPMD, + PROLEMGMT_CMD_ARGS pCmdArgs + ) +{ + uint32_t dwError = 0; + PMD_ROLE_STATUS nStatus = ROLE_STATUS_NONE; + char* pszStatus = NULL; + + if(!hPMD || + !pCmdArgs || + IsNullOrEmptyString(pCmdArgs->pszRole) || + IsNullOrEmptyString(pCmdArgs->pszTaskUUID)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_CLI_ERROR(dwError); + } + + dwError = rolemgmt_get_status( + hPMD, + pCmdArgs->pszRole, + pCmdArgs->pszTaskUUID, + &nStatus); + BAIL_ON_CLI_ERROR(dwError); + + dwError = rolemgmt_status_to_string(nStatus, &pszStatus); + BAIL_ON_CLI_ERROR(dwError); + + fprintf(stdout, "Status: %s\n", pszStatus); + +cleanup: + return dwError; + +error: + goto cleanup; +} + +uint32_t +rolemgmt_cli_alter_cmd( + PPMDHANDLE hPMD, + PROLEMGMT_CMD_ARGS pCmdArgs, + PMD_ROLE_OPERATION nOperation + ) +{ + uint32_t dwError = 0; + char *pszConfigJson = NULL; + char *pszTaskUUID = NULL; + uint32_t dwOffset = 0; + uint32_t dwEntriesToFetch = 1; + PPMD_ROLEMGMT_TASK_LOG pTaskLogs = NULL; + uint32_t dwTaskLogCount = 0; + PMD_ROLE_STATUS nStatus = ROLE_STATUS_NONE; + + if(!hPMD || + !pCmdArgs || + IsNullOrEmptyString(pCmdArgs->pszRole)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_CLI_ERROR(dwError); + } + + if(nOperation == ROLE_OPERATION_ENABLE && + IsNullOrEmptyString(pCmdArgs->pszConfigFile)) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_CLI_ERROR(dwError); + } + + if(!IsNullOrEmptyString(pCmdArgs->pszConfigFile)) + { + dwError = file_read_all_text(pCmdArgs->pszConfigFile, &pszConfigJson); + BAIL_ON_CLI_ERROR(dwError); + } + + dwError = rolemgmt_alter( + hPMD, + pCmdArgs->pszRole, + nOperation, + pszConfigJson, + &pszTaskUUID); + BAIL_ON_CLI_ERROR(dwError); + + fprintf(stdout, + "Add role task for %s is queued with id: %s\n", + pCmdArgs->pszRole, + pszTaskUUID); + + nStatus = ROLE_STATUS_IN_PROGRESS; + while(nStatus == ROLE_STATUS_IN_PROGRESS) + { + dwError = rolemgmt_get_status( + hPMD, + pCmdArgs->pszRole, + pszTaskUUID, + &nStatus); + BAIL_ON_CLI_ERROR(dwError); + + dwError = rolemgmt_get_log( + hPMD, + pszTaskUUID, + dwOffset, + dwEntriesToFetch, + &pTaskLogs, + &dwTaskLogCount); + if(dwError == ERROR_PMD_ROLE_TASK_NO_LOGS || dwError == ERROR_PMD_NO_DATA) + { + dwError = 0; + } + else if(!dwError && pTaskLogs) + { + dwError = print_task_logs(pTaskLogs, dwTaskLogCount); + BAIL_ON_CLI_ERROR(dwError); + } + BAIL_ON_CLI_ERROR(dwError); + + //wait a bit + sleep(1); + dwOffset += dwTaskLogCount; + } + + if(pTaskLogs != NULL) + { + fprintf(stdout, "log = %s\n", pTaskLogs[0].pszLog); + } + +cleanup: + PMD_SAFE_FREE_MEMORY(pszConfigJson); + PMD_SAFE_FREE_MEMORY(pszTaskUUID); + return dwError; + error: goto cleanup; } diff --git a/tools/cli/rolemgmt/rolemgmt_parseargs.c b/tools/cli/rolemgmt/rolemgmt_parseargs.c index 762ddf0..f895b3b 100644 --- a/tools/cli/rolemgmt/rolemgmt_parseargs.c +++ b/tools/cli/rolemgmt/rolemgmt_parseargs.c @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,7 +12,6 @@ * under the License. */ - #include "includes.h" static ROLEMGMT_CMD_ARGS _opt = {0}; @@ -24,8 +23,18 @@ static struct option pstOptions[] = {OPT_DOMAINNAME, required_argument, 0, 0},//--domain {OPT_PASSWORD, required_argument, 0, 0},//--pass {OPT_SPN, required_argument, 0, 0},//--spn + {"config", required_argument, 0, 0}, + {"enable", no_argument, 0, 0}, + {"update", no_argument, 0, 0}, + {"remove", no_argument, 0, 0}, {"list", no_argument, 0, 0}, + {"logs", no_argument, 0, 0}, + {"prereqs", no_argument, 0, 0}, + {"name", required_argument, 0, 0}, + {"status", no_argument, 0, 0}, + {"taskid", required_argument, 0, 0}, {"version", no_argument, &_opt.nShowVersion, 1}, //--version + {"help", no_argument, &_opt.nShowHelp, 1}, {0, 0, 0, 0} }; @@ -91,6 +100,10 @@ rolemgmt_parse_args( pCmdArgs->nShowHelp = _opt.nShowHelp; pCmdArgs->nShowVersion = _opt.nShowVersion; + if(_opt.nShowVersion) + { + pCmdArgs->nOperation = ROLEMGMT_OPERATION_VERSION; + } dwError = collect_extra_args( optind+1,//Move index up to start after component id @@ -105,6 +118,9 @@ rolemgmt_parse_args( pCmdArgs->nShowHelp = 1; } + dwError = rolemgmt_validate_options(pCmdArgs); + BAIL_ON_CLI_ERROR(dwError); + *ppCmdArgs = pCmdArgs; cleanup: @@ -124,18 +140,101 @@ rolemgmt_parse_args( uint32_t rolemgmt_validate_options( - const char *pszName, - const char *pszArg, PROLEMGMT_CMD_ARGS pCmdArgs ) { uint32_t dwError = 0; - if(!pszName || !pCmdArgs) + if(!pCmdArgs) + { + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_CLI_ERROR(dwError); + } + + if(pCmdArgs->nOperation == ROLEMGMT_OPERATION_VERSION && + IsNullOrEmptyString(pCmdArgs->pszRole)) { + fprintf(stderr, + "Specify a role name with --name to do this operation\n"); dwError = ERROR_PMD_INVALID_PARAMETER; BAIL_ON_CLI_ERROR(dwError); } + else if(pCmdArgs->nOperation == ROLEMGMT_OPERATION_PREREQS) + { + if(IsNullOrEmptyString(pCmdArgs->pszRole)) + { + fprintf(stderr, + "Specify a role name with --name to do this operation\n"); + dwError = ERROR_PMD_INVALID_PARAMETER; + } + BAIL_ON_CLI_ERROR(dwError); + } + else if(pCmdArgs->nOperation == ROLEMGMT_OPERATION_ENABLE) + { + if(IsNullOrEmptyString(pCmdArgs->pszRole)) + { + fprintf(stderr, + "Specify a role name with --name to do this operation\n"); + dwError = ERROR_PMD_INVALID_PARAMETER; + } + else if(IsNullOrEmptyString(pCmdArgs->pszConfigFile)) + { + fprintf(stderr, + "Specify a config file name with --config to do this operation\n"); + dwError = ERROR_PMD_INVALID_PARAMETER; + } + BAIL_ON_CLI_ERROR(dwError); + } + else if(pCmdArgs->nOperation == ROLEMGMT_OPERATION_REMOVE) + { + if(IsNullOrEmptyString(pCmdArgs->pszRole)) + { + fprintf(stderr, + "Specify a role name with --name to do this operation\n"); + fprintf(stderr, + "--config might be required. Please refer to your role docs.\n"); + dwError = ERROR_PMD_INVALID_PARAMETER; + } + BAIL_ON_CLI_ERROR(dwError); + } + else if(pCmdArgs->nOperation == ROLEMGMT_OPERATION_UPDATE) + { + if(IsNullOrEmptyString(pCmdArgs->pszRole)) + { + fprintf(stderr, + "Specify a role name with --name to do this operation\n"); + fprintf(stderr, + "--config might be required. Please refer to your role docs.\n"); + dwError = ERROR_PMD_INVALID_PARAMETER; + } + BAIL_ON_CLI_ERROR(dwError); + } + else if(pCmdArgs->nOperation == ROLEMGMT_OPERATION_STATUS) + { + if(IsNullOrEmptyString(pCmdArgs->pszRole)) + { + fprintf(stderr, + "Specify a role name with --name to do this operation\n"); + dwError = ERROR_PMD_INVALID_PARAMETER; + } + else if(IsNullOrEmptyString(pCmdArgs->pszTaskUUID)) + { + fprintf(stderr, + "Specify a task id with --taskid to do this operation\n"); + dwError = ERROR_PMD_INVALID_PARAMETER; + } + BAIL_ON_CLI_ERROR(dwError); + } + else if(pCmdArgs->nOperation == ROLEMGMT_OPERATION_LOGS) + { + if(IsNullOrEmptyString(pCmdArgs->pszTaskUUID)) + { + fprintf(stderr, + "Specify a task id with --taskid to do this operation\n"); + dwError = ERROR_PMD_INVALID_PARAMETER; + } + BAIL_ON_CLI_ERROR(dwError); + } cleanup: return dwError; @@ -151,6 +250,8 @@ rolemgmt_options_error( ) { uint32_t dwError = 0; + int nNumOptions = 0; + int nFound = 0; if(!pszName) { @@ -158,17 +259,41 @@ rolemgmt_options_error( BAIL_ON_CLI_ERROR(dwError); } - if((!strcmp(pszName, "--add") || - !strcmp(pszName, "--delete") || - !strcmp(pszName, "--configure")) - && IsNullOrEmptyString(pszArg)) + nNumOptions = sizeof(pstOptions) / sizeof(pstOptions[0]) - 1; + while(nNumOptions) + { + --nNumOptions; + if(pstOptions[nNumOptions].name && + !strcmp(pszName, pstOptions[nNumOptions].name)) + { + nFound = 1; + break; + } + } + + if(!nFound) + { + fprintf(stderr, "There is no such option: %s\n", pszName); + dwError = ERROR_PMD_CLI_NO_SUCH_OPTION; + BAIL_ON_CLI_ERROR(dwError); + } + + if(!strcmp(pszName, "--name") && + IsNullOrEmptyString(pszArg)) { fprintf(stderr, "Option %s requires an argument\n", pszName); dwError = ERROR_PMD_INVALID_PARAMETER; BAIL_ON_CLI_ERROR(dwError); } + else if(!strcmp(pszName, "--config") && + IsNullOrEmptyString(pszArg)) + { + fprintf(stderr, "Option %s requires an argument\n", pszName); + dwError = ERROR_PMD_INVALID_PARAMETER; + BAIL_ON_CLI_ERROR(dwError); + } cleanup: return dwError; @@ -191,25 +316,51 @@ rolemgmt_parse_option( BAIL_ON_CLI_ERROR(dwError); } - dwError = rolemgmt_validate_options(pszName, pszArg, pCmdArgs); - BAIL_ON_CLI_ERROR(dwError); - if(!strcasecmp(pszName, "list")) { pCmdArgs->nOperation = ROLEMGMT_OPERATION_LIST; } - else if(!strcasecmp(pszName, "add")) + else if(!strcasecmp(pszName, "logs")) + { + pCmdArgs->nOperation = ROLEMGMT_OPERATION_LOGS; + } + else if(!strcasecmp(pszName, "version")) + { + pCmdArgs->nOperation = ROLEMGMT_OPERATION_VERSION; + } + else if(!strcasecmp(pszName, "name")) { - pCmdArgs->nOperation = ROLEMGMT_OPERATION_SET; - dwError = PMDAllocateString(pszArg, &pCmdArgs->pszRole); BAIL_ON_CLI_ERROR(dwError); } - else if(!strcasecmp(pszName, "delete")) + else if(!strcasecmp(pszName, "prereqs")) { - pCmdArgs->nOperation = ROLEMGMT_OPERATION_DELETE; - - dwError = PMDAllocateString(pszArg, &pCmdArgs->pszRole); + pCmdArgs->nOperation = ROLEMGMT_OPERATION_PREREQS; + } + else if(!strcasecmp(pszName, "enable")) + { + pCmdArgs->nOperation = ROLEMGMT_OPERATION_ENABLE; + } + else if(!strcasecmp(pszName, "config")) + { + dwError = PMDAllocateString(pszArg, &pCmdArgs->pszConfigFile); + BAIL_ON_CLI_ERROR(dwError); + } + else if(!strcasecmp(pszName, "remove")) + { + pCmdArgs->nOperation = ROLEMGMT_OPERATION_REMOVE; + } + else if(!strcasecmp(pszName, "update")) + { + pCmdArgs->nOperation = ROLEMGMT_OPERATION_UPDATE; + } + else if(!strcasecmp(pszName, "status")) + { + pCmdArgs->nOperation = ROLEMGMT_OPERATION_STATUS; + } + else if(!strcasecmp(pszName, "taskid")) + { + dwError = PMDAllocateString(pszArg, &pCmdArgs->pszTaskUUID); BAIL_ON_CLI_ERROR(dwError); } cleanup: diff --git a/tools/cli/rolemgmt/structs.h b/tools/cli/rolemgmt/structs.h index 761d4d5..9b7b717 100644 --- a/tools/cli/rolemgmt/structs.h +++ b/tools/cli/rolemgmt/structs.h @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2017 VMware, Inc. All Rights Reserved. + * Copyright © 2016-2019 VMware, Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy @@ -12,14 +12,18 @@ * under the License. */ - #pragma once typedef enum _ROLEMGMT_OPERATION { - ROLEMGMT_OPERATION_LIST = 0x1, - ROLEMGMT_OPERATION_SET = 0x2, - ROLEMGMT_OPERATION_DELETE = 0x4 + ROLEMGMT_OPERATION_LIST = 1, + ROLEMGMT_OPERATION_VERSION, + ROLEMGMT_OPERATION_PREREQS, + ROLEMGMT_OPERATION_STATUS, + ROLEMGMT_OPERATION_ENABLE, + ROLEMGMT_OPERATION_REMOVE, + ROLEMGMT_OPERATION_UPDATE, + ROLEMGMT_OPERATION_LOGS, }ROLEMGMT_OPERATION; typedef struct _ROLEMGMT_CMD_ARGS_ @@ -29,6 +33,9 @@ typedef struct _ROLEMGMT_CMD_ARGS_ int nCmdCount; ROLEMGMT_OPERATION nOperation; char *pszRole; + char *pszName; + char *pszTaskUUID; + char *pszConfigFile; char **ppszCmds; }ROLEMGMT_CMD_ARGS, *PROLEMGMT_CMD_ARGS; diff --git a/tools/pmd.spec.in b/tools/pmd.spec.in new file mode 100644 index 0000000..f46b1cf --- /dev/null +++ b/tools/pmd.spec.in @@ -0,0 +1,285 @@ +# +# pmd spec file +# + +%define _mech_file /etc/gss/mech +%define _mech_id 1.3.6.1.4.1.6876.11711.2.1.2 +%define _python3_sitearch %(python3 -c "from distutils.sysconfig import get_python_lib; import sys; sys.stdout.write(get_python_lib(1))") + +Summary: Photon Management Daemon +Name: pmd +Version: @VERSION@ +Release: 2%{?dist} +Vendor: VMware, Inc. +Distribution: Photon +License: VMware +Url: http://www.vmware.com +Group: Applications/System +Requires: likewise-open >= 6.2.9 +Requires: netmgmt >= 1.0.4-11 +Requires: systemd +Requires: tdnf >= 1.2.0-4 +Requires: vmware-rest >= 1.0.0-3 +Requires: vmware-afd-client +Requires: vmware-directory-client +Requires: jansson +Requires: copenapi >= 0.1-6 +BuildRequires: popt-devel +BuildRequires: rpm-devel +BuildRequires: tdnf-devel >= 1.2.0-4 +BuildRequires: vmware-rest-devel >= 1.0.0-3 +BuildRequires: vmware-afd-client-devel +BuildRequires: vmware-directory-client-devel +BuildRequires: netmgmt-devel >= 1.0.4-11 +BuildRequires: jansson-devel +BuildRequires: copenapi-devel >= 0.1-6 +Source0: %{name}-%{version}.tar.gz + +%description +Photon Management Daemon + +%package cli +BuildRequires: netmgmt-cli-devel >= 1.0.4-2 +Summary: photon management daemon cmd line cli +Requires: likewise-open >= 6.2.0 +Requires: vmware-directory-client + +%description cli +photon management daemon cmd line cli + +%package devel +Summary: photon management daemon client devel +Group: Development/Libraries + +%description devel +photon management daemon client devel + +%package python2 +Summary: Python2 bindings for photon management daemon +Group: Development/Libraries +Requires: python2 >= 2.7 +Requires: %{name}-cli = %{version}-%{release} +BuildRequires: python2-devel >= 2.7 + +%description python2 +Python2 bindings for photon management daemon + +%package python3 +Summary: Python3 bindings for photon management daemon +Group: Development/Libraries +Requires: python3 >= 3.5 +Requires: %{name}-cli = %{version}-%{release} +BuildRequires: python3-devel >= 3.5 + +%description python3 +Python3 bindings for photon management daemon + +%prep +%setup -q + +%build +cd $RPM_BUILD_DIR/%{name}-%{version} +autoreconf -mif +./configure \ + --prefix=%{_prefix} \ + --bindir=%{_bindir} \ + --libdir=%{_libdir} \ + --sysconfdir=/etc \ + --with-likewise=/opt/likewise \ + --with-vmware-rest=/usr/lib \ + --enable-python=no \ + --disable-static +make clean +make + +pushd python +python2 setup.py build +python3 setup.py build +popd + +%install +cd $RPM_BUILD_DIR/%{name}-%{version} +make DESTDIR=%{buildroot} install +rm -f %{buildroot}%{_libdir}/*.la + +pushd python +python2 setup.py install --skip-build --root %{buildroot} +rm -f %{buildroot}%{python_sitearch}/pmd.so +python3 setup.py install --skip-build --root %{buildroot} +popd + +install -d $RPM_BUILD_ROOT/var/log/pmd +install -D -m 444 pmd.service %{buildroot}/lib/systemd/system/pmd.service +install -D -m 444 restconf/restapispec.json %{buildroot}/etc/pmd/restapispec.json +install -D -m 444 api_sddl.conf %{buildroot}/etc/pmd/api_sddl.conf +install -D -m 444 restconf/restconfig.txt %{buildroot}/etc/pmd/restconfig.txt +install -D -m 444 restconf/server.crt %{buildroot}/etc/pmd/server.crt +install -D -m 444 restconf/server.key %{buildroot}/etc/pmd/server.key +install -d $RPM_BUILD_ROOT/etc/pmd.roles.d +install -d $RPM_BUILD_ROOT/etc/pmd.roles.plugins.d +install -D -m 444 example.role %{buildroot}/etc/pmd.roles.d/example.role + +# Pre-install +%pre + + # First argument is 1 => New Installation + # First argument is 2 => Upgrade + +# Post-install +%post + + # First argument is 1 => New Installation + # First argument is 2 => Upgrade + sed -i "s/IPADDRESS_MARKER/`ifconfig eth0 | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1'`/g" /etc/pmd/restapispec.json + /sbin/ldconfig + %systemd_post pmd.service + systemctl daemon-reload + systemctl restart pmd + #open port 81 for REST server + iptables -A INPUT -p tcp --dport 81 -j ACCEPT + #open port 2016 for dcerpc server + iptables -A INPUT -p tcp --dport 2016 -j ACCEPT + #persist firewall info + + if [ ! -d "%{_libdir}/gss" ] ; then + mkdir %{_libdir}/gss + fi + + # Add libgssapi_unix.so to GSSAPI plugin directory + if [ ! -h %{_libdir}/gss/libgssapi_unix.so ]; then + /bin/ln -sf /opt/vmware/lib64/libgssapi_unix.so %{_libdir}/gss/libgssapi_unix.so + fi + # Add gssapi_unix plugin configuration to GSS mech file + if [ -f "%{_mech_file}" ]; then + if [ `grep -c "%{_mech_id}" "%{_mech_file}"` -lt 1 ]; then + echo "unix %{_mech_id} libgssapi_unix.so" >> "%{_mech_file}" + fi + fi + +# Pre-uninstall +%preun + + # First argument is 0 => Uninstall + # First argument is 1 => Upgrade + %systemd_preun pmd.service +if [ "$1" = 0 ]; then + if [ ! -e %{_bindir}/pmd-cli ]; then + # Cleanup GSSAPI UNIX symlink + if [ -h %{_libdir}/gss/libgssapi_unix.so ]; then + rm -f %{_libdir}/gss/libgssapi_unix.so + fi + # Remove GSSAPI SRP plugin configuration from GSS mech file + if [ -f "%{_mech_file}" ]; then + if [ `grep -c "%{_mech_id}" "%{_mech_file}"` -gt 0 ]; then + cat "%{_mech_file}" | sed '/%{_mech_id}/d' > "/tmp/mech-$$" + if [ -s /tmp/mech-$$ ]; then + mv "/tmp/mech-$$" "%{_mech_file}" + fi + fi + fi + fi +fi + + +# Post-uninstall +%postun + + /sbin/ldconfig + + # First argument is 0 => Uninstall + # First argument is 1 => Upgrade + %systemd_postun_with_restart pmd.service + +# Post pmd-cli +%post cli + if [ ! -d "%{_libdir}/gss" ] ; then + mkdir %{_libdir}/gss + fi + + # Add libgssapi_unix.so to GSSAPI plugin directory + if [ ! -h %{_libdir}/gss/libgssapi_unix.so ]; then + /bin/ln -sf /opt/vmware/lib64/libgssapi_unix.so %{_libdir}/gss/libgssapi_unix.so + fi + # Add gssapi_unix plugin configuration to GSS mech file + if [ -f "%{_mech_file}" ]; then + if [ `grep -c "%{_mech_id}" "%{_mech_file}"` -lt 1 ]; then + echo "unix %{_mech_id} libgssapi_unix.so" >> "%{_mech_file}" + fi + fi + +# Pre-uninstall cli +%preun cli + + # First argument is 0 => Uninstall + # First argument is 1 => Upgrade + +if [ "$1" = 0 ]; then + if [ ! -e %{_bindir}/pmd ]; then + # Cleanup GSSAPI UNIX symlink + if [ -h %{_libdir}/gss/libgssapi_unix.so ]; then + rm -f %{_libdir}/gss/libgssapi_unix.so + fi + # Remove GSSAPI SRP plugin configuration from GSS mech file + if [ -f "%{_mech_file}" ]; then + if [ `grep -c "%{_mech_id}" "%{_mech_file}"` -gt 0 ]; then + cat "%{_mech_file}" | sed '/%{_mech_id}/d' > "/tmp/mech-$$" + if [ -s /tmp/mech-$$ ]; then + mv "/tmp/mech-$$" "%{_mech_file}" + fi + fi + fi + fi +fi +# Post-uninstall +%postun cli + /sbin/ldconfig + +%clean +rm -rf %{buildroot}/* + +%files + %defattr(-,root,root,0755) + %{_bindir}/pmd + /lib/systemd/system/pmd.service + /etc/pmd/pmd.conf + /etc/pmd/api_sddl.conf + /etc/pmd/restapispec.json + /etc/pmd/restconfig.txt + /etc/pmd/server.crt + /etc/pmd/server.key + /etc/pmd.roles.d/example.role + %dir /var/log/pmd + %dir /etc/pmd.roles.plugins.d + +%files cli + %{_bindir}/pmd-cli + %{_libdir}/libpmdclient.so.* + +%files devel + %{_includedir}/pmd/*.h + %{_libdir}/libpmdclient.so + %{_libdir}/pkgconfig/pmdclient.pc + +%files python2 + %{python_sitearch}/%{name}/ + %{python_sitearch}/%{name}_python-*.egg-info + +%files python3 + %{_python3_sitearch}/%{name}/ + %{_python3_sitearch}/%{name}_python-*.egg-info + +%changelog +* Thu Jan 12 2017 Priyesh Padmavilasom 0.93-5 +- split python2 and python3 packages. cleanup dependencies +* Tue Oct 4 2016 Priyesh Padmavilasom 0.9-6 +- use copenapi for REST +* Fri Aug 19 2016 Priyesh Padmavilasom 0.9-3 +- python bindings initial +* Wed Aug 3 2016 Priyesh Padmavilasom 0.6 +- http basic and negotiate auth, gssapi_srp auth +* Mon Jul 25 2016 Priyesh Padmavilasom 0.4 +- cmd line fixes for localhost access, error descriptions +* Fri Jul 08 2016 Priyesh Padmavilasom 0.2 +- Integration with netmgmt, tdnf, gssapi_unix +* Mon Jun 27 2016 Priyesh Padmavilasom 0.1 +- Initial build. First version